MVCC原理(多版本并发控制)

MVCC原理(多版本并发控制)

说明

Innodb通过在读取的时刻建立快照,来保证一个事务中的读取一致性。

  • 在该时刻之前的数据是可以查询到的
  • 在该时刻之后的数据是查询不到的
  • 有一个例外需要注意,如果事务修改了该时刻后面的数据,那么当前事务在查询时就会读取到该条数据
演示一
事务A 事务B
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
Empty set (0.00 sec)
mysql> insert into user values(1,'fc');
Query OK, 1 row affected (0.00 sec)
mysql> select * from user;
+----+———+
| id | name |
+----+———+
| 1 | fc |
mysql> select * from user;
Empty set (0.00 sec)

结论:从第一个查询操作开始建立快照,该快照应用于整个事务中。

演示二
事务A 事务B
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
Empty set (0.00 sec)
mysql> select * from user;
Empty set (0.00 sec)
mysql> insert into user values(2,'tt');
Query OK, 1 row affected (0.00 sec)
mysql> select * from user;
+----+———+
| id | name |
+----+———+
| 1 | fc |
+----+------+
1 row in set (0.00 sec)
mysql> select * from user;
Empty set (0.00 sec)
mysql> update user set name = 'xtt' where id = 2;
注意此时事务B的新增语句并没有提交,这里会一直阻塞,等待事务B的提交
mysql> commit;
Query OK, 1 row affected (29.31 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 2 | xtt |
+----+------+
1 row in set (0.00 sec)

总结:如果当前事务A修改其他事务B新增未提交的数据,那么会出现阻塞的情况,直到事务B提交事务。那么如果事务B又将该数据删除了呢,或者事务B是修改了未提交呢?

演示三
事务A 事务B
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
+----+———+
| id | name |
+----+———+
| 2 | tt |
+----+------+
1 row in set (0.00 sec)
mysql> update user set name = 'niufuren' where id =2;
Query OK, 1 row affected (0.00 sec)
mysql> update user set name = 'tt' where id = 2;
注意此时事务B的新增语句并没有提交,这里会一直阻塞,等待事务B的提交
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 等待超时 mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 2 | xtt |
+----+------+
1 row in set (0.00 sec) 这里一致性读,依然读的快照

总结:如果事务B又将该数据删除了呢,或者事务B是修改了未提交,事务A再去删除或者修改该数据时都会阻塞,但是事务A是可以正常读取的,也就是可重复读。

快照的创建

  1. RR隔离级别下:当事务中第一个需要读取的操作时创建快照,也可以通过命令在事务开始时就创建快照

    • 通用select开启事务

    • 通过start transaction with consistent snapshot;

  2. RC隔离界别下:事务中每一个一致性读的操作都会建立自己的新快照

一致性读不适用与DDL语句

  • 当事务A在事务中已经建立了user表的快照是后,其他事务是无法对user表进行DDL的,DDL是直接生效的没有经过事务提交
  • 在RR和RC隔离界别下,一致性读是不会对行加锁的

参考:

https://dev.mysql.com/doc/refman/5.6/en/innodb-consistent-read.html

https://www.cnblogs.com/digdeep/p/4947694.html

猜你喜欢

转载自www.cnblogs.com/fangcheng2018/p/12921344.html