MySQL总结(四)——UNDO LOG REDO LOG 详解

22 篇文章 0 订阅
2 篇文章 1 订阅

本节我们介绍下实现mysql可靠性的两个重要log undo redo log。还是先抛几个问题大家思考思考

 

一、问题

1.事务回滚怎么实现?

2.RC RR级别可见性是怎么实现的?

3.undo redo log 在哪里保存?空间多大?

4.redo log在容灾时起到什么作用?

二、undo log

2.1 先举栗

select * from t1 where id = 1234; 快照一

start transaction; 

udpate t1 set a  = "x2" where id = 1234;快照二

rollback; 快照三

 

2.2 B-tree数据结构分析

快照一

快照二

快照三

2.3 回滚原理

B-tree的叶节点数据结构会存一个Roll Pointer,就是专门用来回滚的。undo log字段表示回滚内容存在的数据段。当开启事务(如快照二) B-tree node会被覆盖,事务id是当前事务,undo log更新,record会保存(x1, x1,z1)这条数据。

rollback执行时,session的TID是43095,根据tid找到修改的记录读取RollPointer里undo log节点数据,覆盖掉B-tree Node 同时这个数据从undo log链表剔除。

 

2.4 可见性原理

undo log也是实现可见性的关键之一。快照二 该数据对其他事务查询依然不可见,怎么实现的呢? 通过MVCC+ReadView方式

ReadView:保存了活跃事务的TID集合,并且事务ID是自增的。RR级别下每开启一个事务都会更新当前活跃事务TID到集合里,RC级别下每开始一个SQL语句,都会更新当前活跃事务TID到集合里。

例如:

事务A(TID:46653)会加入到ReadView这个集合里 [46653]

事务B 在此时执行 select * from id = 1234  返回 (x1,x1,z1) 

mysql查btree发现ROW_TID=46653 

 ROW_TID >=ReadView集合[46653] 说明这条记录的事务还没有提交 RR级别下不可见 

查RollPointer 从undo log链表获取第一条记录,ROW_TID = 40395  <= [46653] 可见 则返回

小结:

BTree Row节点只会存最新的记录 旧的记录会存在undo log这个链表里。事务查数据先查btree节点 然后走链表。数据结构如下图

 

2.5 undo log 日志存储结构

undo log日志是无限大吗?不是的。默认存在ibdata1文件里(和数据行在一个文件),由于undo log时效性很短,大部分旧数据不会读,ibdata有不会自动回收,会导致文件膨胀很快,所以5.7后把undo log 分离并支持在线回收。

数据结构可以想象为Java中的HashMap 数组+链表。 一共128个段,每个段里多个slot,一个row数据放到一个slot里。

 

三、redo log

3.1 LSN

LSN: log sequence number 8个字节。这玩意是数据行的唯一标示 自增的,b-tree redo-log binlog都会记录,目的之一就是为了校准数据。

mysql> show engine innodb status

log sequence number就是当前的redo log(in buffer)中的lsn;
log flushed up to是刷到redo log file on disk中的lsn;
pages flushed up to是已经刷到磁盘数据页上的LSN;

从顺序上可以看出来 先写redo log lsn 再写数据页上。业内常用的可靠性手段——Write-ahead logging

 

3.2 事务提交流程

commit执行步骤

1.写binlog

2.写redo log

3.更新 readview undo log状态  释放各种锁

完成后 事务提交结束 数据才可见。

 

3.3 举栗分析

假设LSN = 100

msql> start transaction; 

msql> udpate t1 set a  = "x2" where id = 1234;  //数据页b-tree node LSN =101

时间点1

msql> commit; 时间点2 //redo log LSN = 101 但此时尚未进行事务后续操作

时间点1 crash recover (MySQL重启后先扫描redo log 做恢复工作)

发现 redo log LSN=100 数据页LSN = 101 则需要回滚 101的事务,从RollPointer找到LSN <=100的数据覆盖。

时间点2 crash recover

发现 redo log LSN=101,把LSN=101的事务进行commit,更新readview undo log,数据可见。

 

小结:

redo log 在recover时候使用,根据log日志来修正数据页数据 保证一致性。

3.4 redo log存储结构 (详细结构: https://yq.aliyun.com/articles/213661

存储数据格式和数据页一样,只会存最近的数据。环形链表结构,写满了直接覆盖。

 

 

3.5 写文件还是写缓存

文件系统经典场景之一 缓存和磁盘策略。

不管是 b-tree数据页还是redo log 都有缓存和落盘的策略。不管才有那种形式,recover时都以redo log来校准,最坏策略在batch_insert下 BufferPool都会丢失,redo log很可能是比较早的数据点。

性能和可靠性 需要业务来取舍。

 

 

四、总结

1.事务回滚怎么实现?

依赖undo log 根据事务ID进行数据修正

2.RC RR级别可见性是怎么实现的?

依赖ReadView 根据事务ID 通过数据页和undo log来取数据

3.undo redo log 在哪里保存?空间多大?

存在类似ibdata文件里;undo log会定期回收,redo log是循环链表

4.redo log在容灾时起到什么作用?

依据WAL策略,根据log日志来修正数据页

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值