【MySQL】MVCC(多版本并发控制)、RR、RC、MySQL中的日志

【摘要】 参考博客:正确的理解MySQL的MVCC及实现原理
一、MVCC是什么?

多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 说人话:维持一个数据的多个版本,使得读写操作没有冲突。(理想概念)

凡是涉及到“写”的并发操作,就可能有线程安全问题要解决。(注意上边是读-写操作) 数据库的…

参考博客:正确的理解MySQL的MVCC及实现原理

一、MVCC是什么?

多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
说人话:维持一个数据的多个版本,使得读写操作没有冲突。(理想概念)

凡是涉及到“写”的并发操作,就可能有线程安全问题要解决。(注意上边是读-写操作)

数据库的并发操作有三种:

  • 读-读:不存在任何问题,也不需要并发控制;
  • 读-写:有线程安全问题,可能会造成事务隔离性问题,例如脏读、幻读、不可重复读;
  • 写-写:有线程安全问题,可能会存在更新丢失问题。

MVCC的好处:
1、提高数据库并发性能,可以在读操作时不用阻塞写操作,或者是写操作时不用阻塞读操作,做到不加锁,非阻塞并发读。
2、可以解决脏读、幻读、不可重复读等事务隔离问题,但不能解决更新丢失问题。

方案:
在这里插入图片描述

二、当前读、快照读

当前读: 读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录加锁。(是悲观锁的实现,实际上可以类比成一个串行的操作,因此容易造成阻塞)

当前读的操作有:select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)等

快照读: 不加锁的非阻塞读。快照读的出现是为了提高并发性能,基于MVCC,虽然避免了加锁,降低了开销,但是快照读可能读到的并不一定是数据的最新版本。

快照读就是MySQL为我们实现MVCC理想模型的其中一个具体非阻塞读功能。

三、MVCC的原理

MVCC模型在MySQL中的具体实现则是由 3个隐式字段undo日志Read View 等去完成的。

3个隐式字段:

1、DB_TRX_ID(6B):存放创建该记录或者最后一次修改该记录的事务ID;
2、DB_ROLL_PTR(7B):回滚指针,指向这条记录的上一个版本;(存储在rollback segment里)
3、DB_ROLL_ID(6B):隐含的自增ID(隐藏主键);如果数据表没有主键,那么InnoDB会自动以DB_ROW_ID来产生一个聚簇索引

undo日志(查看上一步的操作信息):

在这里插入图片描述

undo log实际上就是存在rollback segment中旧记录链。
在这里插入图片描述
就如上边所述,该行的事务ID存放前一个修改/创建该行的事务ID,回滚指针指向前一个操作日志log(undo log),每次一个新的操作完成,log就像“头插法”一样插到undo log里。(但实际上,有的log在事务提交之后可能就被删除丢失了)

ReadView 读视图(判断事务读到的是哪个版本)

在这里插入图片描述

这个图只是描述大概意思。但是其实trx_list上只存放了活跃的事务ID(也就是正在进行的事务),因此,有些不在list中的事务可能也会在快照(ReadView)中。

四、RC和RR

RC和RR都是事务隔离级别,两者主要的区别在于产生快照(Read View)的时机。

RC(read commit): 每次快照读都会新生成一个快照和ReadView;

RR(repeatable read): 同一个事务中的第一个快照读才会创建ReadView,之后的快照读获取的都是同一个ReadView

两者的区别:

在这里插入图片描述

MySQL默认采用RR,而其他几大数据库都是采用RC。

五、MySQL中的日志

参考博客:MySQL中的几种日志了解

  1. 重做日志(redo log)

工作: redo日志记录事务执行后的状态,用来恢复未写入data file的已成功事务更新的数据。
作用: 确保事务的持久性。
场景: 防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。
时机: 事务开始之后
释放: 任务完成

  1. 回滚日志(undo log)

工作: 保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC)
作用: 确保事务的持久性;
场景: 逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。
时机: 事务开始之前
释放: 事务提交之后不能立马被删除,而是放入待清理的链表,由purge线程判断是否由其他事务在使用undo段中表的上一个事务之前的版本信息,决定是否可以清理undo log的日志空间

  1. 二进制日志(binlog)

工作: 逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。
内容: 用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步;用于数据库的基于时间点的还原。
场景: 包括了执行的sql语句(增删改)反向的信息,也就意味着delete对应着delete本身和其反向的insert;update对应着update执行前后的版本的信息;insert对应着delete和insert本身的信息。
时机: 事务提交。
释放: 由参数expire_logs_days配置,非活动的日志文件,超时后自动删除

  1. 错误日志(errorlog)

工作: 记录着mysqld启动和停止,以及服务器在运行过程中发生的错误的相关信息
内容:
场景: 在默认情况下,系统记录错误日志的功能是关闭的,错误信息被输出到标准错误输出。

  1. 普通查询日志(general query log )

工作: 服务器接收到的每一个查询或是命令,无论这些查询或是命令是否正确甚至是否包含语法错误,general log 都会将其记录下来
场景: 系统开销太大,默认关闭。

  1. 慢查询日志(slow query log)

工作: 记录执行时间过长和没有使用索引的查询语句,报错select、update、delete以及insert语句,慢日志只会记录执行成功的语句

  1. 中继日志(relay log)

文章来源: blog.csdn.net,作者:是菜鸟不是咸鱼,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40335368/article/details/116451705

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享