一、MySQL事务的四种隔离级别
读未提交(READ UNCOMMITTED),可以读到其他事务中未commit的数据
读已提交(READ COMMITTED),只能读到其他事务已commit的数据
可重复读(REPEATABLE READ),只能读取到本事务启动之前其他事务已commit的数据
序列化串行(SERIALIZABLE),所有事务串行化,不允许并行执行
通常在关于事务隔离级别的文章中,会提到读脏读、不可重复读、幻读三个数据一致性的问题,而又有很多文章提到只有序列化串行级别才能解决幻读,但是实际上在MySQL中,可重复读级别就能够解决全部三个问题。接下来将对可重复读的原理进行深入讲解。
二、两个关键的数据结构
Undo Log
MySQL中使用一种名为MVCC
的技术实现了读已提交和可重复读,而MVCC
的多个版本的数据正是基于Undo页,Undo页结构如下所示:
MySQL中每一个record中,都会有额外的DB_TRX_ID字段记录了写入或修改该行数据的事务ID,DB_ROLL_PTR字段记录了指向修改之前的数据的指针,所以在MySQL运行期间对每一行数据的修改记录,都会被记录在undo页中。
ReadView
在可重复读的隔离级别下,每个事务在begin时,都会创建一个ReadView
对象,记录了事务begin那一刻所有正在执行的事务,如下图所示(源代码链接):
m_low_limit_id
是当前正在执行的事务的ID的最大值
m_up_limit_id
是当前正在执行的事务的ID的最小值
m_creator_trx_id
是创建该ReadView的事务的ID
m_ids
是所有正在执行的事务的ID的列表
三、源码分析
初始化阶段
为事务创建一个新的ReadView
对象,将此时系统中活跃的事务id记录到对象中