ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

【Mysql面试高频】-Mysql的MVCC机制、Undo和Redo机制?binlog、undo和redo的区别是什么呢?

2021-05-13 13:32:14  阅读:191  来源: 互联网

标签:binlog 事务 log 数据 MVCC undo Mysql 机制 redo


【Mysql面试高频】-Mysql的MVCC机制、Undo和Redo机制?binlog、undo和redo的区别是什么呢?

1 MVCC机制

MVCC(Multi-Version Concurrency Control多版本并发控制)。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。

简单理解:并发访问数据库时(读和写),对正在事务内处理的数据做多版本的管理,以达到用来 避免写操作的拥塞,从而提升读操作的并发问题(基于undo log快照读来解决)。

2 MVCC在MySQL中的体现

在数据库创建表时,比如有idnameage三个字段,但是InnoDB的内部实现中为每一行数据增加了三个隐藏列用于实现MVCC。

列名长度(字节)作用
DB_TRX_ID6插入或更新行的最后一个事务的事务标识符(版本号)。(删除视为更新,将其标记为已删除)
DB_ROLL_PTR7写入回滚段的撤消日志事务标识符(版本号)(若行已更新,则撤消日志记录包含在更新行之前重建行内容所需的信息)
DB_ROW_ID6行标识(自增id,也就是当我们建表没有指定主键列时,mysql会自动生成DB_ROW_ID用作主键)

所以,我们创建表的真正结构,其实是下面这个样子的:

idnameageDB_ROW_IDDB_TRX_IDDB_ROLL_PTR

InnoDB引擎,通过为每一行记录添加两个额外的隐藏的值( DB_TRX_ID、DB_ROLL_PTR )来实现MVCC,这两个值一个记录这行数据何时被创建另外一个记录这行数据何时过期(或者被删除)。并不会存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。下文中,我们就只拿这两个字段+事务版本号来做介绍了。

(1) 插入流程

MVCC在MySQL执行插入操作时,InnoDB会为这个新的数据行,DB_TRX_ID字段记录当前事务版本号执行流程图如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqqgPakB-1620883254970)(imgs\107.png)]

(2)删除流程

MVCC在MySQL执行删除操作时,InnoDB会为要删除的这个行,DB_ROLL_PTR字段记录当前删除(回滚)的事务版本号。执行流程图如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JXbLZMMk-1620883254972)(imgs\108.png)]

(3) 修改流程

MVCC 在 MySQL 执行修改操作时,InnoDB 会写一个这行数据的新拷贝,这个拷贝的版本号为当前的事务版本号(DB_TRX_ID 字段);同时它会将这个事务版本号写到旧行的删除(回滚)版本号中( DB_ROLL_PTR 字段)。执行流程图如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cdk31mVv-1620883254974)(imgs\109.png)]

(4) 查询流程

MVCC在MySQL执行查询操作时,InnoDB查询数据有两条规则:

  • 查找数据行 事务版本号<=当前事务ID的数据行;
  • 查找删除(回滚)版本号为NULL或者删除(回滚)版本号大于当前事务ID的数据行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Te2PiA0M-1620883254977)(imgs\110.png)]

3 MVCC具体实例分析

有两个事务1、2 对数据进行操作。①②③④为执行步骤序号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C0YLWETr-1620883254980)(imgs\111.png)]

(1)情形一

按照步骤 ①②③④②执行操作。流程图如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fwsUJ1hd-1620883254984)(imgs\112.png)]

(2) 情形二

按照步骤 ③④①②执行操作。流程图如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tOvrXQdS-1620883254985)(imgs\113.png)]

(3) 情形分析

我们发现,两个事务A、B 在两种情形下执行相同的操作,但是查询却出现了不同的结果。那么这问题出在了哪里?我们继续向下分析。其实这问题并不是出在 MVCC 上,针对这种情况,InnoDB 引擎又是怎么解决这一问题的呢??这就引出了:undo Log、redo Log 这两个概念。

4 Undo Log(事务的原子性)

在介绍Undo之前,遇到两个问题:(1)加X锁写操作阻塞时,那么数据库在高并发时肯定不行的;(2)使用MVCC控制版本时,又发现一个重复读导致的数据不一致问题。此时:InnoDB引擎就是通过引入undo log,通过读快照的方式来解决这两个问题的。

undo log 的出现,既可以主要解决数据原子性问题的同时,又可以配合 MVCC 间接解决高并发下的读操作阻塞问题。

(1)什么是undo呢?

undo log是指在事务开始之前、操作数据之前,首先将需要操作的数据备份到一个地方的过程。

undo log的出现是为了实现事务的原子性而出现的产物,事务在处理的过程中,如果出现了错误或用户执行了rollback。MySQL可以利用undo log中的备份,将数据恢复到事务开始之前的状态。

在InnoDB引擎中,undo log和MVCC一起来实现MySQL数据的多版本控制。在事务提交之前,undo保存了未提交事务之前的版本到undo log,undo log中的数据可以作为数据旧版本快照来供其它并发事务进行快照读。

(2)快照读和当前读

基于 undo log,可以将 undo log 中的数据作为旧版本快照的方式,来供其他并发事务进行快照读。(这就是 MVCC 配合 undo log 来解决读操作的并发问题)

Ⅰ.快照读 (通过MVCC + undo log 解决幻读问题)
  SQL 读取的数据时快照版本,也就是历史版本。**普通的 Select 就是基于快照读的方式 。**InnoDB 快照读,数据的读取将由 cache(原本数据) + undo(事务修改过的数据)两部分组成。

Ⅱ.当前读 (通过Next-key lock 解决幻读问题)
  SQL 读取的数据时最新版本。通过 锁机制 来保证读取的数据无法通过其他事务进行修改。常用的 update、delete、insert、select xxx LOCK IN SHARE MODE(共享锁)、select xxx FOR UPDATE(排他锁) 都是当前读。

(3)基于undo log实例分析

了解了 undo log 之后,我们 基于 undo log + MVCC 再来按步骤 ③④①② 分析执行结果,图示如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Hf7VEPF-1620883254986)(imgs\114.png)]

执行流程:

  • 执行第④步,update user set age = 18 where id = 1; 会将 user 表中数据备份到 undo buffer 缓存;
  • update 后,如果事务2执行 rollback 操作,那么 user 表会基于 undo buffer 数据回滚到 update 之前状态;(这就是 undo 为了解决事务原子性而出现的产物)
  • 既然已经将旧数据进行备份,InnoDB 引擎就将 undo buffer 当做一个快照表来进行读取;
  • 执行 select age from user where id = 1; 查询时。便会从快照表中读取数据;(这就是为什么 update 加了 X 锁,还能读取数据的原因)
  • undo buffer 是在 cache 缓存中,最终它里面的数据还是会 flush 到 disk 磁盘上的。(undo buffer 是一个缓冲区,是有一定的大小的,如果达到指定大小,事务还未commit/rollback,此时就会写磁盘了)

(4)磁盘中的undo log文件有什么用呢?

如果当前事务在执行过程中,MySQL服务崩溃了,重启时则会从undo log日志中恢复;如果如果断电了,重启后还会根据undo日志进行恢复。此操作具有幂等性,重复多少次都没有问题。

5 Redo Log(事务的持久性)

(1) 什么是Redo log?redo如何实现事务持久性?

redo log是指事务中操作的任何数据,将最新的数据备份到另一个地方的过程。redo log是为了实现事务的持久性而出现的产物。redo log的持久性,并不是随着事务的提交才写入,而是在事务的执行的过程中,便开始写入到redo buffer中,最后以redo log文件方法flush到磁盘中。

redo log的出现,就是放在在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。

(2) redo 日志如何保存

引入 redo log 机制,InnoDB引擎认为数据只要写入到 redo log 成功,就认为当前事务已经完成,而不是要求你将数据全部 flush 到磁盘(*.IBD 文件)才算事务完成。如果每次修改都 flush 数据到磁盘,那显然是很消耗时间的;但是如果你将日志写入到 redo log中,根据 redo log 落盘策略对数据进行保存,显然效率会高很多(即:将耗时的操作放到后台去操作)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QasGAbpz-1620883254994)(imgs\115.png)]

如果此时 MySQL 服务异常、断电等情况,在重启时 MySQL 便会读取 redo log 中的数据来进行恢复。此时你或许会有这样一个疑惑:redo buffer 中的数据还没有来得及写入到 redo log 这部分的数据,不会丢吗?此处就涉及到了 redo buffer 数据 落盘到 redo log 的策略问题。

6 MySql中的binlog、undo log和redo log三者区间是什么?

bin log二进制日志:

作用:用于复制,在主从复制中,从库利用主库上的binlog日志进程重播,从而实现主从同步。

用于数据库的基于时间点的还原。

undo log回滚日志:

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

redo log重做日志:

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

标签:binlog,事务,log,数据,MVCC,undo,Mysql,机制,redo
来源: https://blog.csdn.net/Mind_programmonkey/article/details/116746596

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有