前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL的事务实现原理介绍:undo log、redo log、checkpoint和LSN

MySQL的事务实现原理介绍:undo log、redo log、checkpoint和LSN

作者头像
saintyyu
发布2021-11-22 09:42:40
8720
发布2021-11-22 09:42:40
举报
文章被收录于专栏:IT专栏

参考博客1(建议先通读该博客)介绍了MySQL通过Undo+Redo Log的机制实现了事务的原子性、一致性和持久性(关于事务的隔离性是通过锁机制来保障的,请参考我的另一篇博文MySQL常见的七种锁详细介绍)。文章中提到:

- 用Undo Log实现原子性和持久化的事务的简化过程

- 用Undo + Redo实现原子性和持久化的事务的简化过程

假设有A、B两个数据,值分别为1,2。

假设有A、B两个数据,值分别为1,2.

A.事务开始.

A.事务开始.

B.记录A=1到undo log.

B.记录A=1到undo log.

C.修改A=3.

C.修改A=3.

D.记录B=2到undo log.

D.记录A=3到redo log.

E.修改B=4.

E.记录B=2到undo log.

F.将undo log写到磁盘.

F.修改B=4.

G.将数据写到磁盘.

G.记录B=4到redo log.

H.事务提交

H.将redo log写入磁盘.

I.事务提交

但文章中关于redo log的说明存在前后矛盾:

一方面,文章说在进行恢复时,重做所有事务,包括未提交的事务和回滚了的事务,然后通过undo Log回滚那些未提交的事务;

另一方面又说,在重做redo log时,不关心事务性,在恢复时,没有BEGIN,也没有COMMIT或ROLLBACK的行为。

为什么说这两者相互矛盾呢?文中说了undo log是作为redo log的数据存储在redo log中的。但日志中却并未标记事务的开始,提交或回滚。那么如何能辨别哪些事务未提交呢?按照博客中的说法,redo log中去掉undo log,剩下的日志只能处理回滚了的事务和正常提交的事务,对于未提交的事务是无法处理的。

对于这个疑惑,参考博客2中的描述是比较合理的。在参考博客2中说到:

对于某事务T,在log file的记录中必须开始于事务开始标记(比如“start T”),结束于事务结束标记(比如“end T”、”commit T”)。在系统恢复时,如果在log file中某个事务没有事务结束标记,那么需要对这个事务进行undo操作,如果有事务结束标记,则redo。这里的结束标记就包含commit和rollback。

除此之外,参考博客2中还引出了两个重要的名词:检查点(checkpiont)和幂等性(idempotence)问题。首先我们来说说幂等性。博客中要求日志文件中的操作记录应该具有幂等性,原因是在故障恢复中日志中的记录可能会重复执行多次,如果操作记录不满足幂等性,会造成数据错误。举例来说就是,我们在写增删改等语句的时候,可能并没有明确受影响的记录范围,比如我们在写insert的语句的时候,往往不会限定自增主键id的值,但当Mysql将我们的insert语句记录到redo log日志中时,一定会明确其id值(实际上redo log中存储的是更新后的物理数据页,即物理日志),否则如果执行多次恢复就无法保证幂等性(当然对于insert还需要忽略因记录已经存在而导致插入失败的错误)。再比如对update操作,我们在写update语句的时候,可能会写成在原值的基础上增加或减少一个数值,但redo log中的记录也是变更后的最终值,而不是增量值。除此之外,还有一点非常重要:我们在做多次恢复操作期间,数据库是不能对外提供服务的,否则恢复操作可能会因数据变更而导致数据出错,幂等性也就无从谈起。

再来说说checkpoint。要说checkpoint就不得不提LSN(Log Sequence Number)。我们先了解下为什么要有这两个概念。参考博文3中提到:

InnoDB采用Write Ahead Log策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页。既然有重做日志保证数据持久性,查询时也可以直接从缓冲池页中取数据,那为什么还要刷新脏页到磁盘呢?如果重做日志可以无限增大,同时缓冲池足够大,能够缓存所有数据,那么是不需要将缓冲池中的脏页刷新到磁盘。但显然,服务器的内存是有限的,缓冲池不能缓存全部数据,而且重做日志无限增大,宕机后重做全部日志则的恢复时间会过长。前面提到过,恢复期间,数据库是不能对外提供服务的。为了缩短数据库恢复时间,我们需要一种机制,定期地将日志和数据页持久化到磁盘。该机制还要记录哪些日志在数据恢复时需要执行,哪些已经不需要执行。该机制就是checkpoint,而checkpoint是通过LSN实现的。具体我们看参考博文4:

checkpoint是log日志对数据页刷新到磁盘的操作的检查点,通过LSN号保存记录,作用是当发生宕机等crash情况时,再次启动时会查询checkpoint点,将该检查点之后发生的事务修改恢复到磁盘。

InnoDB引擎通过LSN来标记版本,LSN是日志空间中每条日志的结束点,用字节偏移量来表示。每个数据页有LSN,redo log也有LSN,Checkpoint也有LSN。可以通过命令show engine innodb status来观察。

代码语言:javascript
复制
mysql> show engine innodb status\G;
---
LOG
---
Log sequence number 10623965866
Log flushed up to   10623965866
Pages flushed up to 10623965866
Last checkpoint at  10623965857
0 pending log flushes, 0 pending chkp writes
13 log i/o‘s done, 0.81 log i/o‘s/second

Last checkpoint at就是系统最后一次刷新buffer pool中页数据到磁盘的checkpoint,checkpoint是和redo log进行关联操作的,也就记录在redo log中,checkpoint记录在redo log第一个文件的头部,存储两个值循环更替修改。

LSN(log sequence number)日志序列号,5.6.3之后占用8字节,LSN主要用于发生crash时对数据进行recovery,LSN是一个一直递增的整型数字,表示事务写入到日志的字节总量

LSN不仅只存在于重做日志中,在每个数据页头部也会有对应的LSN号,该LSN记录当前页最后一次修改的LSN号,用于在recovery时对比重做日志LSN号决定是否对该页进行恢复数据。前面说的checkpoint也是有LSN号记录的,LSN号串联起一个事务开始到恢复的过程。

到此我们明白了checkpoint和LSN的工作机制:日志空间中的每条日志对应一个LSN值,而在数据页的头部也记录了当前页最后一次修改的LSN号每次当数据页刷新到磁盘后,会去更新日志文件中的checkpoint,以减少需要恢复执行的日志记录。极端情况下,数据页刷新到磁盘成功后,去更新checkpoint时如果宕机,则在恢复过程中,由于checkpoint还未更新,则数据页中的记录相当于被重复执行,这个时候,前面介绍的幂等性的作用就体现出来了。

参考博客:

1. https://blog.csdn.net/chast_cn/article/details/50910861 MySQL redo与undo

2. https://blog.csdn.net/kobejayandy/article/details/50885693 理解数据库中的undo日志、redo日志、检查点

3. https://blog.csdn.net/melody_mr/article/details/48930739 InnoDB Redo Flush及脏页刷新机制深入分析

4. http://www.mamicode.com/info-detail-1264451.html mysql 之 checkpoint和LSN详解

5. https://blog.csdn.net/Baisitao_/article/details/104723795?utm_source=app MySQL事务是怎么实现的

6. https://www.bbsmax.com/A/D854eYBWdE/ savepoint原理

7. https://www.cnblogs.com/binyang/p/11260126.html  日志系统 SQL更新语句的执行

8.https://blog.csdn.net/qq_38125183/article/details/80652557  redo&undo日志解析

9.详细分析MySQL事务日志(redo log和undo log) 重要

10.https://www.zhihu.com/question/368847138/answer/996629614 InnoDB如何保证redolog的完整性?

11.https://www.jianshu.com/p/fdae2e30b9fa?from=timeline  Redo Log——第一篇

12.https://blog.csdn.net/bohu83/article/details/81481184 MySQL · 引擎特性 · InnoDB redo log 

13.https://blog.csdn.net/bohu83/article/details/81568341 MySQL · 引擎特性 · InnoDB undo log

14.https://www.cnblogs.com/xinysu/p/6586386.html MySQL崩溃恢复过程  重要

15、mysql日志系统 SQL 逻辑日志 物理日志 重要

16、https://blog.csdn.net/anying5823/article/details/104675987/  MySQL原子性与持久性的保证(undo log, redo log与binlog)   重要

17、https://blog.51cto.com/yanzongshuai/2090932  解析MySQL binlog --(6)XID_EVENT、ROTATE_EVENT及stop  :当事务提交时,不论是statement还是row格式的binlog都会添加一个XID_EVENT作为事务的结束。该事件记录了该事务的ID。在mysql进行崩溃恢复时根据binlog中提交的情况来决定是否提交redo log中处于prepared状态的事务。

18、https://www.cnblogs.com/klvchen/p/10861850.html MySQL 重要参数 innodb_flush_log_at_trx_commit 和 sync_binlog

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档