mvcc的实现依赖什么
事务版本号
每次事务开始之前,都会从数据库获取一个【自增长】的事务id,从这个版本号,可以判断事务的先后顺序
隐式字段
对于innodb存储引擎,每行记录都有两个隐藏列,分别是:trx_id、roll_pointer。
trx_id:操作该数据事务的事务id,记录最新一次修改该记录的事务id
roll_pointer:一个指针,指向回滚的undo log
undo log
用于记录数据被修改前的数据,表记录修改前,会先把数据拷贝到undo log中
怎么记录的:
如果是【delete】的时候,undo log 会记录一条【insert】记录
如果是【update】的时候,undo log 会记录一条相反的【update】记录
作用是什么:事务回滚、MVCC快照读
版本链
多个事务并行操作某一行数据的时候,不同事务对该数据的修改会生成多个版本,通过【回滚指针】连在一起,就成了版本链。
快照读和当前读
快照读:读取的是数据记录的可见版本。在加事务,【不加锁】的情况下,都是快照读。
当前读:读取的是数据的最新记录,【显式加锁】都是当前读,比如for update
Read View 读视图
在事务执行sql 语句读时候产生的读视图,主要作用是判断记录的【可见性】,就是用来判断当前事务可以读取哪个版本的数据。
read view 包含以下几个属性
m_ids:当前系统中存在哪些活跃未提交的事务id,是一个列表
min_limit_id:在生成当前read view的时候,当前活跃事务中最小的事务id,就是m_ids中的最小值。
max_limit_id:在生成当前read view的时候,系统应该分配给下个事务的id
creator_trx_id:创建当前read view的事务id
判断规则:
- trx_id < min_limit_id 可见
- trx_id>=max_limit_id 不可见
- min_limit_id<=trx_id<max_limit_id
-
- 在m_ids范围内,需要等于creator_trx_id 可见
- 不在m_ids范围内,可见
MVCC原理
查询记录的流程
- 获取事务版本号,生成read view
- 查询数据,并且和read view 中的事务版本进行比较
- 如果不符合read view中的可见性规则,就需要去undo log中查询历史快照(根据版本链逐级向上递推)
- 最后返回符合要求的数据