我是靠谱客的博主 怕孤单跳跳糖,最近开发中收集的这篇文章主要介绍rr模式下的快照读--更新操作仍然会导致事务前后数据不一致,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

rr模式是快照读,不会有幻读和不可重复读的情况,所以一般来说事务周期内,查询结果是一致的。但是也有例外。

下面通过测试来说明

 

rr模式下,未查询到主键时插入记录也可能造成主键冲突 :

rr,autocommit off,t1.a为主键 
sess1sess2
mysql> begin; 

 

mysql> select * from t1;
+---+------+------+
| a | b    | c    |
+---+------+------+
| 1 | a    |    1 |
| 3 | a    |    3 |
+---+------+------+

 
 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;
+----+--------+------+
| a  | b      | c    |
+----+--------+------+
|  1 | a      |    1 |
|  3 | a      |    3 |
| 11 | insert |   11 |
+----+--------+------+

 

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);
Query OK, 1 row affected (0.00 sec)

--因为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;
Query OK, 1 row affected (0.01 sec)

 

mysql> select * from t1;
+----+------+------+
| a  | b    | c    |
+----+------+------+
|  1 | a    |    1 |
| 44 | lzl  |   33 |
+----+------+------+

--rr模式下,更新数据时(dml)会去验证当前态的数据情况,一但更新到,这个数据就会成为当前事务的最新历史态

 

 

总结:

rr快照读只会读取当前事务下数据的“历史态”,但当更新(dml)时,事务会去查看“当前态”某些数据行,验证数据的可执行性(如主键冲突、唯一性约束冲突等等)。一但有“当前态”的行数据被更新,这个行就会和当前”历史态“数据合并成新的”历史态“,此后该事务的快照读均是读取的新”历史态“快照。

所以rr模式下的快照读仅正对”读“这一个动作,dml都会去验证相关的“当前”数据。ddl因为是自提交的,所以没有这些问题。

 

最后

以上就是怕孤单跳跳糖为你收集整理的rr模式下的快照读--更新操作仍然会导致事务前后数据不一致的全部内容,希望文章能够帮你解决rr模式下的快照读--更新操作仍然会导致事务前后数据不一致所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部