WAL
介绍
WAL 预写日志,是数据库系统中常见的一种用于保证数据操作的原子性和持久性的手段
在WAL系统中所有的修改在提交之前都要先写到log文件中。Log文件包括redo和undo信息。这种记录时便于在机器掉电后检查log文件,对掉电时计划执行的操作和实际上执行的内容进行比较。在这个比较的基础上,程序就可以决定时撤销已做的操作还是继续完成已做的操作或者保持原样。
crash-safe
https://blog.youkuaiyun.com/weixin_42189550/article/details/126442734
两阶段提交:
第一阶段:将数据记录到 redolog buffer中并 fsync到磁盘日志文件中,状态为prepare
第二阶段:
- 将逻辑操作记录到binlog cache中,并fsync到磁盘日志文件中
- 设置redo log的记录为commit状态
mysql进程异常重启了系统会自动去检查redo log,将未写入到mysql的数据从redo log恢复到mysql中去。
当数据库发生异常重启时,系统会自动定位到上次checkpoint的位置,,每个数据页里页存在一个LSN(日志序号),当redo log中的LSN大于数据页中的LSN时,说明重启前redo log中的数据未完全写入,那么从数据页中的LSN开始从 redo log中恢复数据。
对于正在进行的事务,如果还没有到prepare状态,则舍弃,如果达到prepare状态则与binlog比较事务是否完整,如果不完整则根据 undolog进行回滚,完整则 重新commit redolog
对于回滚
没有WAL的做法一般是:在对数据更新前先将原数据copy到一个地方,然后去更新,如果更新失败,可以从备份数据中写回来
WAL的做法是:修改并不会直接写入数据库文件中,而是写入到另一个成为WAL的文件中;如果事务失败,WAL中的记录会被忽略,如果成功他将会根据mysql的策略立即或者在某个时间被入数据库文件中,提交修改
提升磁盘性能
三种提升的方法: 1. 随机读写改顺序读写 2. 缓冲单条读写改批量读写 3. 单线程读写改为并发读写
WAL对于mysql的提升在于:
- 通过将日志中记录的事务更新内容从随机的脏页写入变为顺序的日志刷盘,将日志空间当成一个圆(类似循环数组),通过两个指针wirte pos(写指针)check pos(读指针)顺序记录和刷脏。
- 通过buffer的方式改单条磁盘刷盘入改为缓冲批量刷盘
- 并且从WAL数据到磁盘固化数据的过程中可以采用并发的方式
其他的性能提升
读和写可以完全并发执行,不会堵塞(写写不能并发)
可以在线备份和时间点恢复
磁盘I/O的行为更容易控制
使用更少的fsync()操作
(用 fsync 可以保证文件的修改时间也被更新。fsync 系统调用可以使您精确的强制每次写入都被更新到磁盘中。您也可以使用同步(synchronous)I/O 操作打开一个文件,这将引起所有写数据都立刻被提交到磁盘中。通过在 open 中指定 O_SYNC 标志启用同步I/O。)
缺点
性能可能会降低
WAL对于非常大或者运行时间非常长的食物会引入额外的开销,因为在数据没有刷之前都是存放在同一个队列中
bin log 和 redo log
不同点
redo log 是 innodb引擎特有的 binlog是在server层上实现的
reod log 是物理日志,记录为“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是语句的原始逻辑“sql语句”
redo log 是把内存空间当成一个循环数据,空间会用完,binlog可以追加写入,