MySQL事务日志-Redo与Undo

事务日志


什么是事务日志?

事务要保证ACID的完整性必须依靠事务日志做跟踪,每一个操作在真正写入数据到数据库之前,先写入到日志文件中,比如删除一行数据会先在日志文件中将此行标记为删除,但是数据库中的数据文件并没有发生变化。只有在(包含多个sql语句)整个事务提交后,再把整个事务中的sql语句批量同步到磁盘上的数据库文件中。在事务引擎上的每一次写操作都需要执行两遍如下过程:

  1. 先写入日志文件中写入日志文件中的仅仅是操作过程,而不是操作数据本身,所以速度比写数据库文件速度要快很多。
  2. 再写入数据库文件中写入数据库文件的操作是重做事务日志中已提交的事务操作的记录。

日志组

一般不止设置一个日志文件,一个文件写满之后使用另外一个日志文件提高服务器效率。日志文件的日志同步到磁盘后空间会自动释放,单个日志文件不宜设置过大,如果日志文件过大,MySQL进程在把日志同步到数据文件的时候会崩溃。

事务日志用途

事务日志可以帮助提高事务的效率,使用事务日志,存储引擎在修改表的数据的时候只需要修改其内存拷贝,再把该行为记录到持久在磁盘的事务日志中,而不是每次都将修改的数据本身持久到磁盘。事务日志采用的是追加方式,因此磁轭日志的操作在磁盘上一小块区域的顺序IO,而不像随机IO需要磁盘在的多个地方移动。所以采用事务日志的方式相对来说要快的多。事务日志持久后,内存中的修改在后台慢慢的刷回磁盘。期间如果系统发生崩溃,存储引擎在重启的时候依靠事务日志自动回复这部分被修改的数据。

Redo log(重做)

在InnoDB的存储引擎中,事务日志通过重做(redo)日志和InnoDB存储引擎的日志缓冲(InnoDB Log Buffer)实现。事务开启时,事务中的操作,都会先写入存储引擎的日志缓冲中,在事务提交之前,这些缓冲的日志都需要Buffer Pool中映射的数据文件才会慢慢刷新到磁盘。此时如果数据库崩溃或者宕机。那么当系统重启进行恢复时,就可以根据redo log中的记录的日志,把数据库恢复到崩溃前的一个状态。未完成的事务,可以继续提交,也可以选择回滚,这是基于恢复的策略而定。
在系统启动的时候,就已经为redo log分配了一个连续的存储空间,以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。所有的事务共享redo log的存储空间。它们的Redo Log按照语句的执行顺序,依次交替的记录在一起。如下一个简单示例:

记录1:<trx1,insert...>
记录2:<trx2,delete...>
记录3:<trx3,pdate...>
记录4:<trx1,update...>
记录5:<trx3,insert...>

InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小为1GB,那么这块“粉板”总共就可以记录4GB的操作。

redo log包括两部分:一是内存中的日志缓冲(redo log buffer),该日志是易失性的;二是磁盘上的重做日志文件(redo log file),该日志是持久的。
在概念上,InnoDB通过force log at commit机制实现事务的持久性,即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。
为了 确保每次日志都能写入到事务日志文件中,在每次将log buffer中的日志写入日志文件的过程中都会调用一次操作系统的fsync操作(fsync函数同步内存中所有已经修改的文件数据到存储设备)。因为MySQL是在用户控件工作的,其的log buffer处于用户空间的内存中。要写入到磁盘的log file中(redo:ib_logfileN文件,undo:share tablespace或.ibd文件),中间还要经过操作系统内核空间的os buffer,调用fsync()的作用是将os buffer中的日志刷到磁盘的log file中。
也就是说,从redo log buffer写日志到磁盘的redo log file 中,过程如下:

用户空间->内核空间->磁盘


在此需要注意一点,一般所说的log file并不是磁盘上的物理日志文件,而是操作系统缓存中log file。
在主从复制结构中,要保证事务的持久性和一致性,需要对日志相关变量设置为如下:如果启用了二进制日志,则设置sync_binlog=1,即每提交一次事务同步写到磁盘中。
总是设置inndb_flush_log_at_trx_commit=1,即每提交一次事务都写到磁盘中。上次两项变量的设置保证了每次提交事务都写入二进制日志和事务日志,并在提交时将它们刷新到磁盘中。选择刷日志的时间会严重影响数据修改时的性能,特别是刷到磁盘的过程。

undo log(撤销还原)

特点:

 

  1. 是数据修改前的备份,主要是保证用户的读一致性;
  2. 在事务修改数据时产生;
  3. 至少保存到事务结束;

undo log主要为事务的回滚服务。在事务执行过程中,处理记录redo log,还会记录一定量的undo log。undo log记录了数据在每个操作前的状态,如果事务执行过程中需要回滚,就可以根据undo log进行回滚操作。单个事务的回滚,只会回滚当前事务做的操作,并并不会影响到其他事务做的操作。
示例:
假设有2个数值,分别为A=1和B=2,然后将A修改为3,B修改为4。

start transaction;
记录A=1到undo log;
update A=3;
记录A=3到redo log;
记录B=2到undo log;
update B=4;
记录B=4到redo log;
将redo log刷新到磁盘;
commit;

在1-8步骤的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响。如果在8-9之间宕机,恢复之后可以选择回滚,也可以选择继续完成事务的提交,因为此时redo log已经持久化。若在9之后系统宕机,内存映射中变更的数据来不及刷回磁盘,那么系统恢复之后,可以根据redo log把数据刷回磁盘。所以,redo log其实保证了事务的持久性和原子性,而undo log则保证了事务的一致性。undo log是逻辑日志,可以理解为:

  • 当delete一条记录时,undo log中会记录一条对应的insert记录;
  • 当insert一条记录时,undo log中会记录一条对应的delete记录;
  • 当update一条记录时,会记录一条对应相反的update记录;

为什么要保持读一致性?
比如有两个用户访问数据库,当然并发罗。A是更改,B是查询。

  • A更改还没有提交,B查询的话,数据肯定为历史数据,这个历史数据就是来源于UNDO段;
  • A更改未提交,需要回滚rollback,回滚rollback的数据也来至于UNDO段;

 

Undo与Redo的区别

  1. undo记录数据修改之前的操作,redo记录磁盘数据将要进行的操作;
  2. undo用于数据的回滚操作和实现一致性读,redo用于前滚数据库操作;
  3. undo存储在回滚段中,redo存储在重做日志文件里;
  4. undo用于在多用户并发的系统里保证一致性读,redo用于防止数据丢失;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值