问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

MySQL事务原理深度剖析:MVCC与Read View详解

创作时间:
作者:
@小白创作中心

MySQL事务原理深度剖析:MVCC与Read View详解

引用
CSDN
1.
https://blog.csdn.net/m0_74823983/article/details/145213897

事务是数据库系统中非常重要的概念,而MVCC(多版本并发控制)和Read View是实现事务隔离的关键技术。本文将深入解析MVCC和Read View的工作原理,帮助读者理解MySQL事务处理的核心机制。

事务隔离级别回顾

在深入讲解MVCC和Read View之前,我们先回顾一下事务隔离级别的概念:

  • 脏读(Dirty Read):一个事务读取到另一个事务未提交的数据。
  • 不可重复读(Non-repeatable Read):一个事务在两次读取之间,另一个事务修改了数据。
  • 幻读(Phantom Read):一个事务在两次读取之间,另一个事务插入了新的数据行。
  • 读未提交(Read Uncommitted):允许脏读、不可重复读和幻读。
  • 读已提交(Read Committed):解决脏读问题,但存在不可重复读和幻读。
  • 可重复读(Repeatable Read):解决脏读和不可重复读,但某些数据库可能有幻读问题。
  • 串行化(Serializable):通过加锁机制,完全避免并发问题。

一致性与并发控制

事务执行的结果必须使数据库从一个一致性状态变到另一个一致性状态。一致性是通过原子性保证的。在并发场景下,需要解决以下问题:

  • 读读并发:不存在任何问题,不需要并发控制。
  • 读写并发:可能造成事务隔离性问题,如脏读、幻读、不可重复读。
  • 写写并发:可能造成更新丢失问题。

MVCC基础:隐藏字段

MySQL在表中添加了三个隐藏字段来支持MVCC:

  • DB_TRX_ID:记录最后操作这条数据的事务ID。
  • DB_ROLL_PTR:指向undo log中的历史数据。
  • DB_ROW_ID:隐藏的自增ID,如果没有主键,InnoDB会自动使用这个字段作为聚簇索引。

Undo日志

Undo日志是MySQL中的一段内存缓冲区,用于记录事务的回滚操作。当一个事务需要修改数据时,会先将数据复制到undo log中,然后进行修改。例如,事务10将"张三"修改为"李四":

事务11接着修改年龄为28:

这样就形成了一个版本链,如果需要回滚,可以从undo log中恢复历史数据。

MVCC多版本控制

MVCC通过版本链实现数据的多版本控制。undo log管理的是一个事务内所形成的版本链条。对于insert操作,虽然可以形成版本链,但一旦commit,这个版本链就会被清空。而对于update和delete操作,由于可能有其他事务在访问这条记录,所以版本链可能不会立即被清空。

Read View

Read View是事务进行快照读操作时生成的读视图,记录系统当前活跃事务的ID。其结构如下:

class Readview
{
private:
    trx_id_t m_low_limit_id;  // 高水位,大于等于这个ID的事务均不可见。
    trx_id_t m_up_limit_id;  // 低水位,小于这个ID的事务均可见。
    trx_id_t m_creator_trx_id;     // 创建该Read view的事务ID。    
    ids_t m_ids; // 创建视图时的活跃事务id列表。
    trx_id_t m_low_limit_no; 
    bool m_closed;  // 视图是否关闭
    //....省略       
};

Read View的生成和使用规则:

  • 已提交事务:如果版本链中的事务ID与m_ids中的最小ID相同或更小,那么该版本数据是可见的。
  • 正在操作的事务:如果版本链中的事务ID在m_ids列表中,那么该版本数据是不可见的。
  • 新启动的事务:如果版本链中的事务ID大于low_limit_id,那么该版本数据是不可见的。

RC与RR的本质区别

通过两个实验来说明RC(Read Committed)和RR(Repeatable Read)的区别:

实验一:RR隔离级别

  1. 开启两个事务,都进行快照读。
  2. 左边事务修改数据并commit。
  3. 查看右边事务的数据,发现数据没有变化。

实验二:RR隔离级别

  1. 开启两个事务,但右边事务不立即进行快照读。
  2. 左边事务修改数据并commit。
  3. 右边事务进行快照读,发现数据已经变化。

这是因为RR隔离级别只在第一次快照读时生成Read View,而RC隔离级别每次快照读都会生成新的Read View,因此能够看到其他事务的提交结果。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号