MySQL - 日志

1. 回滚日志(undo log

作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读

内容:逻辑格式的日志(当delete一条记录是,记录一条对应的insert记录,反之亦然),在执行undo log的时候,仅仅是将数据从逻辑上恢复至事务之前的状态

释放:当事务提交之后,undo log并不能立马被删除,而是放入待清理的链表,通过判断是否由其他事务在使用undo log的版本信息,决定是否可以清理

1)保证原子性,在数据修改的时候,不仅记录了redo log,还记录了对应的undo log,如果因为某些原因事务失败而回滚,可以借助该undo log进行回滚。

2)当执行rollback时,可以从undo log中的逻辑记录读取到相应的内容并进行回滚

3)当读取带某一行的其他事务锁定时,它可以从undo log中分析出改行记录以前的数据是什么,从而提供该行版本信息,让用户实现MVCC

2. 重做日志(redo log

作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启MySQL时,根据redo log进行重做,从而达到事务的持久性这一特性

内容:物理格式的日志,记录的是物理数据页面的修改的信息

产生:事务开始之后就产生redo log,不是随着事务的提交才写入的

释放:当对应事务的脏页写入到磁盘之后,redo log的使命也就完成了,redo log的空间就可以重用(被覆盖)

3. 二进制日志(bin log

作用:用于在主从复制中,从库利用主库上的binlog进行重播,实现主从同步;用于数据库的基于时间点的还原。

内容:逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。 而且还包括了执行的sql语句(增删改)反向的信息

产生:事务提交的时候,一次性将事务中的sql语句(一个事务可能对应多个sql语句)按照一定的格式记录到binlog中(对于较大事务的提交,可能会变得比较慢一些)

注意:与redo log的差异:redo log不是在事务提交的时候刷新到磁盘,因此对于事务的提交,即便是较大的事务,提交(commit)都是很快的

释放:binlog的默认是保持时间由参数expire_logs_days配置,在生成时间超过配置的天数之后,会被自动删除。

4. redo logbin log对比

1)redo log是属于InnoDB层面,binlog属于MySQL Server层面的

2)redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑

3)redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖

4)binlog可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用

5. redo log buffer

一块内存,写redo log时,先修改内存redo log buffer,再【按时】,或者当【事务提交】时写入磁盘

问题:redo log buffer的内容未刷到磁盘,会丢吗

如果事务执行期间MySQL发生异常重启,那这部分日志就丢了,但是由于事务并没有提交,所以这时日志丢了也不会有损失

问题:事务还没提交的时候,redo log buffer中的部分日志可能被持久化到磁盘呢

1)后台线程每秒一次的轮询操作

2)redo log buffer占用的空间即将达到一定阈值时,后台线程会主动写盘

3)并行的事务提交的时候,顺带将这个事务的redo log buffer持久化到磁盘

6. MySQL 的“双 1”配置

1)sync_binlog设置成1

0表示每次提交事务都只write,不fsyncwrite指把日志写入到文件系统的page cache,并没有持久化到磁盘)

1表示每次提交事务都会执行fsync

N(N>1) 时表示每次提交事务都write,但累积N个事务后才fsync

2)innodb_flush_log_at_trx_commit设置成1

0表示每秒触发一次缓冲日志写磁盘操作,写入效率最高,数据安全最低。

1表示立即将redo log buffer写入redo log file,数据安全最高,性能受到影响(最安全,推荐)

2表示将redo log buffer刷新到OS Cache(内核缓冲区Page Cache),然后依托OS每秒刷新一次写入redo log file

7. 两阶段提交

redo logprepare完成,再写binlog,最后才进入redo log commit阶段

预提交:当一个事务执行时,将事务ID和操作记录到redo log buffer,同时将对应的事务状态设置为prepare,再将redo log持久化到磁盘

确认提交:把事务ID写入到binlog,然后将binlog持久化到磁盘,接着调用引擎的提交事务接口,将redo log状态设置为commit(此时并不没有持久化到磁盘)

说明:此时没有持久化到磁盘,而是write到文件系统的page cache中,因为只要binlog写磁盘成功,就算redo log的状态还是prepare也没有关系,一样会被认为事务已经执行成功

1)时刻A MySQL宕机

由于此时binlog还没写,redo log也还没提交,所以崩溃恢复的时候,这个事务会回滚

2)写binlog时崩溃

重启后会根据redo记录中的事务ID,回滚前面已写入的数据。

3)时刻B MySQL宕机

如果redo log里面的事务是完整的,也就是已经有了commit标识,则直接提交;

如果redo log里面的事务只有完整的prepare,则判断对应的事务binlog是否存在并完整:

1)如果是,则提交事务

2)否则,回滚事务

 

 

 

 

posted on 2024-01-21 22:32  小桔子1024  阅读(20)  评论(0)    收藏  举报