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

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

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

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

引用
CSDN
1.
https://m.blog.csdn.net/m0_54854484/article/details/145480304

MySQL的事务隔离机制是数据库系统中的核心概念之一,其中MVCC(多版本并发控制)和read view机制在实现高并发读写操作中扮演着重要角色。本文将深入探讨MVCC的工作原理,以及在不同隔离级别(Read Committed和Repeatable Read)下read view的具体表现,帮助读者理解这些复杂的数据库概念。

事务隔离级别的回顾

在深入讲解MVCC和read view之前,我们先回顾一下事务隔离性的四种级别:

  • 脏读(Dirty Read):一个事务读到另一个事务未提交的数据。
  • 不可重复读(Non-repeatable Read):一个事务两次读取同一数据,但两次结果不同,因为有其他事务修改并提交了该数据。
  • 幻读(Phantom Read):一个事务两次读取同一范围的数据,但两次结果不同,因为有其他事务插入了新的数据。
  • 隔离级别
  • 读未提交(Read Uncommitted):允许脏读、不可重复读和幻读。
  • 读已提交(Read Committed):避免脏读,但可能有不可重复读和幻读。
  • 可重复读(Repeatable Read):避免脏读和不可重复读,某些数据库可能有幻读问题,但MySQL解决了幻读问题。
  • 串行化(Serializable):完全避免所有并发问题,但性能最低。

一致性

事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一种一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改变未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确的状态。因此一致性是通过原子性保证的。

三种并发方式的安全隐患

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

三个隐藏字段

在InnoDB存储引擎中,每条记录都会自动添加三个隐藏字段:

  • DB_TRX_ID:6字节,记录最后修改这条数据的事务ID。
  • DB_ROLL_PTR:指向undo日志的位置,用于回滚操作。
  • DB_ROW_ID:隐藏的自增ID,如果没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引。

Undo日志

Undo日志是MySQL中的一段内存缓冲区,用于记录事务的回滚操作。当需要修改数据时,MySQL会先将数据保存一份到undo日志中,然后再进行修改。这样即使事务回滚,也可以从undo日志中恢复数据。

例如,假设有一条数据:

当事务10想要修改这条数据时,会先将数据加锁,然后复制一份到undo日志中,再进行修改:

事务10提交后,释放锁。如果事务11也想要修改这条数据,会重复相同的过程:

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

MVCC多版本控制

MVCC(Multi-Version Concurrency Control)是一种无锁的并发控制机制,通过维护数据的多个版本来实现并发控制。在MVCC中,每个事务都有自己的事务ID,通过事务ID来判断事务的先后顺序。

  • Undo log:管理事务内形成的版本链条。一个事务多次修改会形成版本链,commit时undo log会被清空。
  • Insert:虽然没有版本链,但insert对应的数据也要放到undo log里面,commit后版本链可以被清空。
  • Update和Delete:可能有其他事务在访问,不一定能立即清空。

Read View

Read View是事务进行快照读操作时生成的读视图,记录系统当前活跃事务的ID。Read View是一个类,与事务的关系类似于进程地址空间和PCB。

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_up_limit_id,说明事务启动得更早,可以看见。
  • 如果版本链中的事务ID大于m_low_limit_id,说明事务启动得更晚,不能看见。

RC与RR的本质区别

  • RC(Read Committed):每次快照读都生成新的Read View,low_limit_id总是当前系统最大的事务ID,只要其他事务提交,就能看到其修改。
  • RR(Repeatable Read):只在第一次快照读时生成Read View,之后的修改都基于这个Read View判断可见性,因此在事务持续期间,读到的数据不会发生变化。

通过实验可以验证:

  • 在RR隔离级别下,如果一个事务在另一个事务commit后才进行快照读,那么它可以看到前一个事务的修改。
  • 在RC隔离级别下,每次快照读都会生成新的Read View,因此能立即看到其他事务的提交结果。

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