概述
为了提高并发MySQL加入了多版本并发控制,它把旧版本记录保存在了共享表空间,在事务未提交之前对应的行记录还是受到锁的限制,当事务提交之后对应的记录行就在缓存中被修改了记录也被持久化了,当刷新线程按一定的规律进行刷新的时候行的修改记录被刷新到了物理数据页中,并且共享表空间的中的旧版本记录页也被清除。
正文
多版本并发控制只针对innodb的repeatable read和read committed这两种隔离级别。多版本并发控制的原理就是在每个记录行后面增加两个标示列用来存储该行的状态,分别存储改行的新系统版本号和删除系统版本号。
版本号:系统的版本号会随着每增加一个事务递增。
通过阅读高性能mysql这本书的解释是MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
TABLE
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
有四个事务:select(trx=2),insert(trx=3),delete(trx=4),update(trx=5)
现在这四个事务同时对该行进行操作,演示SELECT的可重复读,假设四个操作在SLECT提交之前都未提交,当然SELECT是能查看到四个操作的记录的。
SELECT:
SELET会根据以下两个条件去查找记录:
1.只查找小于或等于当前事务版本号的记录行。
2.删除版本号为空或者大于当前事务版本号的记录行。
BEGIN TRAN SELECT NAME FROM TABLE WHERE ID=1
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
WAIT 10 MINUTE SELECT NAME FROM TABLE WHERE ID=1 COMMIT
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
4 |
根据SELECT 的查找条件INSERT记录的事务版本号大于当前版本号所以不会被查到;DELETE的事务删除版本号大于当前版本号,所以该行会被查出;UPDATE第一行的事务的版本号小于当前版本号而删除版本号大于当前版本号,可以被查到,第二行因为事务版本号大于当前版本号所以不满足,最终SELECT查询的记录是UPDATE操作的第一条记录;SELECT两次查询的结果一致,满足可重复读隔离级别。当然在这里除了INSERT操作,其它的操作都无法在SELECT提交之前提交。
INSERT:
INSERT INTO TABLE(ID,NAME) VALUES(2,‘B‘);
ID |
NAME |
Trx_id |
De_Trx_id |
2 |
b |
2 |
DELETE:
DELETE FROM TABLE WHERE ID=1;
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
3 |
UPDATE:
BEGIN TRAN UPDATE TABLE SET NAME=‘B‘ WHERE ID=1 COMMIT
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
a |
1 |
4 |
ID |
NAME |
Trx_id |
De_Trx_id |
1 |
b |
4 |
注意:多版本并发控制不支持myisam存储引擎。
总结
在缓存中有一个用于维护锁的资源,对锁的维持需要消耗mysql的资源,多版本并发控制它就是减少了用于维持锁资源的消耗来提高性能。