事务并发执行遇到的问题
- 脏写(Dirty Write)
- 如果一个事务修改了另一个未提交事务修改过的数据,那就意味着发生了脏写
- 脏读(Dirty Read)
- 如果一个事务读到了另一个未提交事务修改过的数据,那就意味着发生了脏读
- 不可重复读(Non-Repeatable Read):第二次读到的数据和第一次不一样
- 幻读(Phantom)
- 如果一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来,那就意味着发生了幻读
SQL标准中的四种隔离级别
- READ UNCOMMITTED:未提交读:可能发生脏读、不可重复读和幻读问题。
- READ COMMITTED:已提交读:可能发生不可重复读和幻读问题,但是不可以发生脏读问题。
- REPEATABLE READ:可重复读:可能发生幻读问题,但是不可以发生脏读和不可重复读的问题。
SERIALIZABLE:可串行化:各种问题都不可以发生。
MySQL的默认隔离级别为REPEATABLE READ
MVCC原理
版本链
隐藏列:
- trx_id:每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的事务id赋值给trx_id隐藏列。
- roll_pointer:每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
- 每次对记录进行改动,都会记录一条undo日志,每条undo日志也都有一个roll_pointer属性(INSERT操作对应的undo日志没有该属性,因为该记录并没有更早的版本),可以将这些undo日志都连起来,串成一个链表

- 所有的版本都会被roll_pointer属性连接成一个链表,我们把这个链表称之为版本链,版本链的头节点就是当前记录最新的值。另外,每个版本中还包含生成该版本时对应的事务id
ReadView
- 概述:判断一下版本链中的哪个版本是当前事务可见的
- m_ids:表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。
- min_trx_id:表示在生成ReadView时当前系统中活跃的读写事务中最小的事务id,也就是m_ids中的最小值。
- max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的id值。
creator_trx_id:表示生成该ReadView的事务的事务id。
READ COMMITTED —— 每次读取数据前都生成一个ReadView
- REPEATABLE READ —— 在第一次读取数据时生成一个ReadView0
