Mysql 的MVCC原理
MVCC机制
Multi Version Concurrency Control , Mysql的可重复读(Repeatable-Reads,默认)隔离级别的隔离性,就是通过该机制来实现. 通过对数据的读写互斥,保证隔离性,避免频繁互斥加锁.
串行化(Serialization):通过给所有操作都进行加锁来保证最高的隔离性.
另外 Mysql 在读已提交(Read-Commit) 和 重复读(Repeatable-Read)隔离级别 都有MVCC机制.
begin 或者 start transaction 不是事务的起点. 事务的起点是,在执行begin 或者 start transaction 之后第一个操作Innodb的语句, 事务才算是启动. 这时mysql才会分配 trx_id. mysql内部严格按照事务的启动顺序来分配事务id;
读已提交(RC) 和 可重复读(RR) MVCC的区别
读已提交(RC) : 每次查询都会创建 read view ;
可重复读(RR) : 在事务未提交前,一直使用第一次查询创建的read view;
Undo Log 日志版本链 和 Read View 机制
Undo 日志版本链: 一行数据呗多个事务修改,每个事务在修改完之后,Mysql 会保留修改之前的数据 保存在undo log 回滚日志中. 同时,使用 隐形字段 trx_id 和 roll_pointer 将日志串联起来形成历史记录版本链.
可重复读(RR)的隔离级别 开启事务时, 执行查询sql 会生成事务的一致性视图(read view) .在事务结束前,这个read view 都不会发生改变. read view 由 所有未提交事务id数组 和 最大已提交事务id 组成 ([min_id],max_id). 事务中的sql查询都需要 将本身的trx_id 和 read view 中的事务trx_id进行对比.
版本链对比规则
1.如果trx_id ∈(-∞,min_id),表示这个版本是已提交的事务生成,那么这个数据是可见状态;
2.如果trx_id ∈(max_id,+∞),表示这个版本是由即将启动的事务生成,是不可见状态(但如果trx_id是自己本身的事务id,那么就是可见状态);
3.如果trx_id ∈ [min_id,max_id] 存在两种情况:
a.如果trx_id在视图数组中,那么这个版本就是由没有提交的事务生成,属于不可见状态
(如果是本身的trx_id,那么就是可见状态);
b.如果trx_id不在数组范围中,表示这个版本是由已经提交的事务生成,属于可见状态;
readview:[100,200], 300 —>100就是min_id,300就是 max_id;
Delete事务过程
删除的情况可以认为是 特殊的update操作,会将版本链上最新的数据进行复制,将trx_id 修改成删除操作的trx_id.同时,在数据的记录头(record header) 的标记位(delete_flag) 上标记为 true, 表示当前数据已经被删除. 在查询数据时,如果数据前的标记位(delete_flag) 为true 那么就表示这条数据已经被删除,不返回数据.