MySQL中的Undo Log、Redo Log
Undo log
Undo Log介绍
Undo:意为撤销或取消,以撤销操作为目的,将数据返回到某个状态的操作(有点类似ctrl+z
)。
Undo Log:数据库事务开始之前,会将要修改的记录存放到 Undo 日志里,当事务回滚时或者数
据库崩溃时,可以利用 Undo 日志,撤销未提交事务对数据库产生的影响。
Undo Log产生和销毁:Undo Log在事务开始前产生;事务在提交时,并不会立刻删除Undo
Log,innodb会将该事务对应的undo log放入到删除列表中,后面会通过后台线程purge thread进
行回收处理。Undo Log属于逻辑日志,记录一个变化过程。例如执行一个delete语句,Undo Log会记
录一个insert语句;执行一个update语句,Undo Log会记录一个相反的update语句。
Undo Log存储:Undo Log采用段的方式管理和记录。在innodb数据文件中包含一种rollback
segment回滚段,内部包含1024个Undo Log segment。
可以通过下面一组参数来控制Undo log存
储:
mysql> show variables like '%innodb_undo%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_undo_directory | ./ |
| innodb_undo_log_truncate | OFF |
| innodb_undo_logs | 128 |
| innodb_undo_tablespaces | 0 |
+--------------------------+-------+
Undo Log作用
实现事务的原子性
Undo Log 是为了实现事务的原子性而出现的产物。事务处理过程中,如果出现了错误或者用户执
行了 ROLLBACK 语句,MySQL 可以利用 Undo Log 中的备份将数据恢复到事务开始之前的状态。
实现多版本并发控制(MVCC)
Undo Log 在MySQL InnoDB存储引擎中用来实现多版本并发控制。事务未提交之前,Undo Log
保存了未提交之前的版本数据,Undo Log 中的数据可作为数据旧版本快照供其他并发事务进行快
照读。
事务A手动开启事务,执行更新操作,首先会把更新命中的数据备份到Undo Buffer中。
事务B手动开启事务,执行查询操作,会读取Undo日志数据返回,进行快照读,这样可以实现事务隔离级别的读已提交。
Redo log
Redo Log介绍
Redo:顾名思义就是重做。以恢复操作为目的,在数据库发生意外时重现操作(类似ctrl+y)。
Redo Log:指事务中修改的任何数据,将最新的数据备份存储的位置(Redo Log),被称为重做
日志。
Redo Log的生成和释放:随着事务操作的执行,就会生成Redo Log,在事务提交时会将产生
Redo Log写入Log Buffer,并不是随着事务的提交就立刻写入磁盘文件。等事务操作的脏页写入
到磁盘之后,Redo Log的使命也就完成了,Redo Log占用的空间就可以重用(被覆盖写入)。
Redo Log工作原理
Redo Log 是为了实现事务的持久性而出现的产物。防止在发生故障的时间点,尚有脏页未写入表
的IBD文件中,在重启MySQL服务的时候,根据Redo Log进行重做,从而达到事务的未入磁盘
数据进行持久化这一特性。
疑问:事务提交后直接刷盘不就好了,为什么还要记录一份数据到redo log中呢,redo log也得刷盘后才能保证事务成功?
事务提交后表数据的刷盘与redo log数据的刷盘同样都是IO操作,表数据的刷盘是随机IO,而redo log数据的刷盘是顺序IO,顺序IO比随机IO更快。
Redo Log写入机制
Redo Log文件内容是以顺序循环的方式写入文件,写满时则回溯到第一个文件,进行覆盖写。
如图所示:
- write pos是当前记录的位置,一边写一边后移,写到最后一个文件末尾后就回到 0 号文件开
头; - checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数
据文件;
write pos和checkpoint之间还空着的部分,可以用来记录新的操作。如果write pos追上
checkpoint,表示写满,这时候不能再执行新的更新,得停下来先擦掉一些记录,把checkpoint
推进一下。
Redo Log相关配置参数
每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组至少有2个重做日志文
件,默认为ib_logfile0和ib_logfile1。可以通过下面一组参数控制Redo Log存储:
mysql> show variables like '%innodb_log%';
+-----------------------------+----------+
| Variable_name | Value |
+-----------------------------+----------+
| innodb_log_buffer_size | 16777216 |
| innodb_log_checksums | ON |
| innodb_log_compressed_pages | ON |
| innodb_log_file_size | 50331648 |
| innodb_log_files_in_group | 2 |
| innodb_log_group_home_dir | ./ |
| innodb_log_write_ahead_size | 8192 |
+-----------------------------+----------+
Redo Buffer持久化到Redo Log的策略,可通过innodb_flush_log_at_trx_commit
设置:
- 0:每秒提交 Redo buffer ->OS cache -> flush cache to disk,可能丢失一秒内的事务数
据。由后台Master线程每隔 1秒执行一次操作。 - 1(默认值):每次事务提交执行 Redo Buffer -> OS cache -> flush cache to disk,最安
全,性能最差的方式。 - 2:每次事务提交执行 Redo Buffer -> OS cache,然后由后台Master线程再每隔1秒执行OS
cache -> flush cache to disk 的操作。
一般建议选择取值2,因为MySQL 挂了数据没有损失,整个服务器挂了才会损失1秒的事务提交数
据。
mysql> show variables like '%Innodb_flush_log_at_trx_commit%';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
还没有评论,来说两句吧...