以下这些话,加深对mvcc的认识
-
使用mvcc(multiversion concurrency control)实现的行级锁(row-level lock,不是简单行锁(synchronized),锁住后就不能读写来保证数据完整性,虽然行锁已经降低了系统开销,但是限制并发),【提高事务并发】(transactional features such as concurrency and rollback)
-
mvcc可以看作是数据快照,在同一时间同一数据行,对于不同事务内可以看到不同数据
-
mvcc保证了数据在事务中的连续性,就是在同一个事务中,用户只能看到该事务之前已经生效的和该事务本身做的修改。
-
mvcc“乐观性”,理念“事务基本都能成功,少数失败”,所以把修改应用到原数据行上,提交快,回滚比较麻烦需要找undo log,再改回去
-
mvcc只能用于的事务隔离级别,REPEATABLE READ(mysql默认隔离级别)和READ COMMITTED
-
【大数据量,批处理,超长事务期间】,需要周期性commit,否则undo logs和rollback segment可能占满表空间
-
事务内删除不是立刻物理删除行,而是设置标志,在事务完成,清空undo log时,但是速度很快,所以在【持续时间长小批处理】进行插入同时删除时,可能由于时间差,导致由于undo log与dead row没有及时清理而数据越来越大
下面是InnoDB的mvcc实现:
-
InnoDB的每行有三个隐藏域
6-byte DB_TRX_ID 行事务id, 上次事务id,上次事务插入或修改时变化,就是经常被提起的【创建版本号】或【删除版本号】,其中有1bit删除标志 7-byte DB_ROLL_PTR 回滚指针,指向undo log, undo log存储于rollback segment区域 6-byte DB_ROW_ID 行id,可以理解为隐藏的主键,插入新行时产生的一个单调增id,不是+1
-
每次的新事务id是+1
-
在curd时的mvcc处理
delete,设置删除标志,在事务结束后,清理与真正删除 insert,新建行,设置DB_TRX_ID, DB_ROW_ID update, 把原始值与DB_TRX_ID记录到undo log, DB_ROLL_PTR指向undo log(多个事务的修改会形成链表), 然后在原始行内修改 select, 先得到当前系统内的所有活跃事务列表, 比较【行DB_TRX_ID】与【事务列表中的事务id】 DB_TRX_ID < 列表事务id,说明没有事务在该行(没有被修改过),可见 否则就说明可能有其他事务在该行(不能直接显示原始行的值) 从undo log 开始遍历找到第一个事务id<DB_TRX_ID的值作为可见值,来显示
Show engine InnoDB status
...
Transactions
------------
Trx ID Counter0 430621
Purge Done forTrx\'s N:o < 0 430136 undo N:o < 0 0
History List Length7
...
网上流传很多的,【隐藏的两列,创建版本号和删除版本号】不完全正确
mysql 5.7 doc–14.3 InnoDB Multi-Versioning
从源码看Mysql Innodb中undo-log和MVCC多版本一致性读 的实现
The following table shows the modes and concurrency levels for different locks in MySQL.
Lock Policy | Concurrency of | Overhead | Engine |
---|---|---|---|
Table | Minimum | Minimum | Myisam,merge,memory |
Yes | High | High | NDB Cluster |
Line and MVCC | Highest | Highest | Innodb,falcon,pbxt,solidd |