代码改变世界

MySQL-MVCC

2023-01-02 16:15  杭伟  阅读(84)  评论(0编辑  收藏  举报

首先MVCC不是MySQL才有的概念,它是一种思想,一种方法论。

MVCC全称:Multi-Version Concurrency Control 多版本并发控制

最早于1978年,论文『Naming and Synchronization in a Decentralized Computer System』清晰地介绍了 MVCC,这是公认关于 MVCC 最早的工作。

在1981年,论文『Concurrency Control in Distributed Database System』介绍了MVCC的一些细节。

目前支持 MVCC 的数据库,包括 DB2、Oracle、Sybase、SQL Server、MySQL、PG 等所有主流数据库,以及 HBase、Couchbase、Berkeley DB 等 NoSQL 数据库。

可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,
但大多实现了非阻塞的读操作,写操作也只锁定必要的行。--《高性能MySQL》

 

实现原理:

上一篇我们有简单提过这样一句:MVCC处理快照读相关问题。

这里介绍一下当前读和快照读的概念:

当前读:一种加锁操作,永远读的是最新版本,以下操作都是当前读

select lock in share mode(共享锁)

select for update(排他锁)

update(排他锁),insert(排他锁),delete(排他锁)

串行化事务隔离级别

 

快照读:读到的不一定是最新的数据,有可能是历史版本的数据

不加锁的select操作(事务隔离级别不是串行化)

MVCC里的读仅指快照读。即不通过加锁方式,以提高查询效率和性能。

 

主要由三个部分内容组合实现:undolog,三个隐藏字段,read view

undo log:回滚日志,在进行insert,update,delete时生成的回滚日志。

三个(隐藏列)字段

DB_TRX_ID 记录插入或更新(删除)该行的最后一个事务的ID
DB_ROLL_PTR 回滚指针指向回滚段的撤销日志记录
DB_ROW_ID 没有指定主键和唯一键时自动生成的聚簇索引的ID值

由undo log和三个隐藏字段组成了版本链:

 

ReadView(快照)

ReadView将决定从上面的版本链中(快照)读哪一条记录,从源码中可以看到它的主要构成: 

m_low_limit_id:m_ids中的最小值,     >=它的,都不可见

m_up_limit_id:m_ids中的最大值+1,  <它的,都可见

m_creator_trx_id:生成该ReadView时的事务的事务id       =它的,都可见

m_ids:生成该ReadView时当前系统中活跃的读写事务的事务id列表      在m_ids里面不可见,否则可见

还有其它字段定义未被列出,大部分字段的定义,都是为了确保这份ReadView能否被其它事务“看见”的条件,即可见性。

待续。