Mysql 事务可见性

Mysql 为了控制事务隔离,防止数据跑偏采用了多种机制来保证事务的准确性;

背景:

1、log

使用(write ahead log),落盘前先写log;

事务开始的时候就记录undo log,用于失败回滚;

事务提交的时候会记录redo log,可以用来回放保证事务提交的一致性;当然redo log 也不一定都会提交,这个涉及到事务的两阶段提交;

2、事务标记

每条记录都会记录一个事务id,用于标记记录当前所处的上下文环境;

事务是连续性的(事务id trx_id是在系统变量max_trx_id自增);

只有写操作事务id才会自增;

事务id 的大小为8个字节,也就是自增到8个字节后就会从0开始,这个时候就会出现【脏读】;

3、MVCC

MVCC即版本控制,原始的版本控制是串行的,类似于悲观锁,Mysql的MVCC一条记录是可以有多个版本,即乐观锁;

事务中可见性如何保证:

每条记录都包含一个 trx_id 标记记录的事务id;

当mysql 开启一个事务的时候,会记录这个事务中数据的上下文信息 read view:

read view 生成时机:

RC 每次读操作都会生成read view, 比较消耗资源;

RR 事务的首次读操作会生成read view;

read view 中关键数据:up_trx_id(低水位事务id) - low_trx_id(高水位事务id),以及这个阶段的活跃事务id 列表;

读操作读取数据判断是否可见:

如果数据的trx_id 小于 低水位事务id,则表示数据的事务已经提交,可见;

如果数据的trx_id 大于 高水位事务id,则表示数据的事务id 是在当前事务之后,不可见,在undo log中读取旧版本数据;

如果数据的trx_id 在 低水位事务id 和 高水位事务id 之间,则表示数据在当前事务开启的时候正处于一个未提交事务中,当然在生成read view 的时候可能事务已经提交,

所以:

如果事务id在低水位 - 高水位之间,且在read view 列表中,则表示在生成read view 时仍然未提交事务,则可以读取 undo log中的数据;

如果事务id在低水位 - 高水位之间,但是不在read view列表中,则表示在生成read view的时候已经提交了事务,则数据可见,直接使用;

 

posted @ 2021-10-12 11:33  lion_eagle  阅读(668)  评论(0编辑  收藏  举报