概述
rr模式是快照读,不会有幻读和不可重复读的情况,所以一般来说事务周期内,查询结果是一致的。但是也有例外。
下面通过测试来说明
rr模式下,未查询到主键时插入记录也可能造成主键冲突 :
rr,autocommit off,t1.a为主键 | |
sess1 | sess2 |
mysql> begin; | |
mysql> select * from t1; | |
mysql> select * from t1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | a | 1 | | 3 | a | 3 | +---+------+------+ | |
mysql> insert into t1 values(11,'insert',11); | |
mysql> select * from t1; +----+--------+------+ | a | b | c | +----+--------+------+ | 1 | a | 1 | | 3 | a | 3 | | 11 | insert | 11 | +----+--------+------+ | |
mysql> commit; | |
mysql> select * from t1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | a | 1 | | 3 | a | 3 | +---+------+------+ | |
mysql> insert into t1 values(11,'insert',11); ERROR 1062 (23000): Duplicate entry '11' for key 'PRIMARY' | |
mysql> commit; | |
mysql> select * from t1; |
rr模式下主键冲突仍然插入了数据:
begin | |
mysql> select * from t1; +----+--------+------+ | a | b | c | +----+--------+------+ | 1 | a | 1 | | 11 | insert | 11 | +----+--------+------+ | |
mysql> select * from t1; +----+--------+------+ | a | b | c | +----+--------+------+ | 1 | a | 1 | | 11 | insert | 11 | +----+--------+------+ | |
mysql> commit; | |
mysql> select * from t1; +----+--------+------+ | a | b | c | +----+--------+------+ | 1 | a | 1 | | 11 | insert | 11 | +----+--------+------+ | |
--看上去已经有主键11了,但是仍然显示插入成功 mysql> insert into t1 values(11,'insert',11); --因为rr快照读的特性,导致select查询的历史态数据,而更新数据需要去验证当前态的数据状态 | |
mysql> select * from t1; +----+--------+------+ | a | b | c | +----+--------+------+ | 1 | a | 1 | | 11 | insert | 11 | +----+--------+------+ | |
rr模式虽然是可重复读,但是仍然会发生同一事务内读取到其他事务数据的情况:
mysql> begin; | |
mysql> select * from t1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | a | 1 | +---+------+------+ | |
mysql> select * from t1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | a | 1 | +---+------+------+ | |
mysql> insert into t1 values(33,'lzl',33); mysql> commit; | |
mysql> select * from t1; +----+------+------+ | a | b | c | +----+------+------+ | 1 | a | 1 | | 33 | lzl | 33 | +----+------+------+ | |
mysql> select * from t1; +---+------+------+ | a | b | c | +---+------+------+ | 1 | a | 1 | +---+------+------+ | |
--更新一条在当前事务中不存在的行,更新成功。 mysql> update t1 set a=44 where a=33; | |
mysql> select * from t1; --rr模式下,更新数据时(dml)会去验证当前态的数据情况,一但更新到,这个数据就会成为当前事务的最新历史态 |
总结:
rr快照读只会读取当前事务下数据的“历史态”,但当更新(dml)时,事务会去查看“当前态”某些数据行,验证数据的可执行性(如主键冲突、唯一性约束冲突等等)。一但有“当前态”的行数据被更新,这个行就会和当前”历史态“数据合并成新的”历史态“,此后该事务的快照读均是读取的新”历史态“快照。
所以rr模式下的快照读仅正对”读“这一个动作,dml都会去验证相关的“当前”数据。ddl因为是自提交的,所以没有这些问题。
最后
以上就是怕孤单跳跳糖为你收集整理的rr模式下的快照读--更新操作仍然会导致事务前后数据不一致的全部内容,希望文章能够帮你解决rr模式下的快照读--更新操作仍然会导致事务前后数据不一致所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复