附录:RR隔离级别与幻读
程序员文章站
2022-06-14 15:30:22
...
转载自: http://blog.sina.com.cn/s/blog_499740cb0100ugs7.html
幻读。解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。但是,如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。
注意描述里的字眼“本事务再更新时”,这样结合下面两个栗子就很容易理解了。
用比喻来理解幻读
比喻:假如,中午去食堂打饭吃,看到一个座位是空的,便屁颠屁颠的去打饭,回来后,发现这些座位都还是空的(重复读),窃喜。走到跟前刚准备坐下时,却惊现一个恐龙妹,严重影响食欲。仿佛之前看到的空座位是“幻影”一样。
sql实现来理解幻读
首先设置隔离级别为RR(set tx_isolation='REPEATABLE-READ';
)
然后开启两个事务,事务A在Session A
中执行,事务B在Session B
中执行。
栗子1
t Session A Session B
|
| START TRANSACTION; START TRANSACTION;
|
| SELECT * FROM t_bitfly;
| empty set
| INSERT INTO t_bitfly
| VALUES (1, 'a');
|
| SELECT * FROM t_bitfly;
| empty set
| COMMIT;
|
| SELECT * FROM t_bitfly;
| empty set
|
| INSERT INTO t_bitfly VALUES (1, 'a');
| ERROR 1062 (23000):
| Duplicate entry '1' for key 1
v (shit, 刚刚明明告诉我没有这条记录的)
如此就出现了幻读,以为表里没有数据,其实数据已经存在了,傻乎乎的提交后,才发现数据冲突了。
栗子2
t Session A Session B
|
| START TRANSACTION; START TRANSACTION;
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id | value |
| +------+-------+
| | 1 | a |
| +------+-------+
| INSERT INTO t_bitfly
| VALUES (2, 'b');
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id | value |
| +------+-------+
| | 1 | a |
| +------+-------+
| COMMIT;
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id | value |
| +------+-------+
| | 1 | a |
| +------+-------+
|
| UPDATE t_bitfly SET value='z';
| Rows matched: 2 Changed: 2 Warnings: 0
| (怎么多出来一行)
|
| SELECT * FROM t_bitfly;
| +------+-------+
| | id | value |
| +------+-------+
| | 1 | z |
| | 2 | z |
| +------+-------+
|
v
本事务中第一次读取出一行,做了一次更新后,另一个事务里提交的数据就出现了。也可以看做是一种幻读。
InnoDB引擎不存在幻读问题。它是MySQL的默认隔离级别
上一篇: MySQL InnoDB事务隔离级别脏读、可重复读、幻读
下一篇: c#创建文件,自动创建文件夹