189 8069 5689

linux提权命令ch,linux提权方式

Mysql:RR隔离级别下的幻读

众所周知,Mysql在InnoDB下有四种隔离级别:

创新互联-专业网站定制、快速模板网站建设、高性价比红旗网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式红旗网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖红旗地区。费用合理售后完善,10年实体公司更值得信赖。

未提交读(Read Uncommitted)

提交后读(Read Committed)

可重复读(Repeatable Read)

串行化(Serializable)

其中可重复读(RR)可以避免脏读( a事务读到b事务回滚前的数据)以及可不重复读( a事务在b事务修改提交的前后,两次分别读到的数据不一致)。但是对于幻读(a事务在b事务insert提交前后,两次分别读到的数据不一致),却存在争议。

下面我们来做一个试验:

对于下面这张简单的数据表

id        num

1         11

2         22

3         33

我们开启a、b两个事务

a事务                b事务

begin                begin

select * from tb    ----

----                    insert into tb (id,num)values(4,44)

----                    commit

select * from tb    ----

commit

试验结果:a事务的两次select查询到的结果相同,在后一次查询中没有返回新插入id=4的那条记录。

据此,很多人判断说RR隔离级别下“不存在”幻读。

但果真如此吗?----

出现上面的试验结果,是因为在RR隔离级别事务下,Mysql会对前一次select的结果快照。所以第二次select其实是快照读(这也正是RR隔离级别下能够避免不可重复读的策略)。

如果我们把试验条件稍作修改,同样开启a、b两个事务:

a事务                b事务

begin                begin

select * from tb    ----

----                    insert into tb (id,num)values(5,55)

----                    commit

update tb set num=num+1    ----        #此处a事务做一次修改操作

select * from tb    ----

commit

试验结果:在a事务的第二次select中出现了b事务新插入的id=5的记录。

由于做了update操作,之前的快照失效了,所以说RR隔离级别下的快照策略并没能真正避免幻读。

ps. 假如给第二次的select查询上锁(无论是共享锁还是排它锁),也会得到同样的结果,都会令快照失效。

mysql在RR隔离级别下,某些特定场景下出现幻读

见图,主要是select xx for update,又或者是update语句更新了,使用了当前读。所以后面再次select(13行)出现幻读,如果只是select的话(10行不是update,是个select),是不会出现幻读的情况,因为符合mvcc规则,用的还是一开始的快照。

todo:看下10行是update的情况下的内容:SELECT * FROM information_schema . INNODB_TRX

如果10行,update的id为1,则不会出现幻读的情况,这里因为update的时候把session2里的更新到了

Mysql 幻读&Next Key Lock详解

幻读的定义是指,一个事务开启后,执行前后两次查询,两次查询中出现了新的数据,幻读仅针对数据的新增。

比如: 表t中,id为主键,目前有数据1,5,10,20四条。

开始一个事务A,前后两次执行 select * from t where id 10 for update;

开启一个事务B,在事务A第二次执行查询前,执行insert into t values( 2,...); 并提交事务(请暂时忽略这里能否成功执行!)。

此时在RC、RR隔离级别下都会导致事务A第二次查询能够查询到 事务B新增的数据 id = 2。

RC级别下能够看到不同结果就不做解释了。

对于RR隔离级别下,有了MVCC版本控制为什么还能读取到不同的结果呢?

这里要归功于 "for update"。

"for update" 会将快照读变为当前读,在当前读场景中,会自动读取最新的数据,而非快照数据。

分析一下,锁与当前读关系。了解什么情况下会加锁。了解 意向锁、共享锁、排它锁区别及各自在什么情况下使用。

行锁的概念都清楚,这里就不做补充了。

间隙锁实际上是指一个区间。

我们都知道,InnoDB 在RR事务隔离级别下解决幻读问题就是通过Next Key Lock (间隙锁+行锁)来实现的。而且,很多地方也有提到,如果对于读一致性要求不高的场景可以考虑使用RC隔离级别,允许幻读的发生。

还是上边说的那个实例,略微改动:

比如: 表t中,id为主键,目前有数据1,5,10,20四条。

开始一个事务A,前后三次分别执行

开启一个事务B,在事务A执行update前,执行insert into t values( 2,...); 并提交事务。

此时我们知道,事务A中第二次查询能够查到 事务B新增的数据,也就是产生了幻读。那么,按照SQL执行的顺序来说,事务B

关于MySQL的幻读问题,看这一篇就够了

什么是幻读?

幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。

首先快照读是不存在幻读的,只有当前读(实时读)才存在幻读的问题。

幻读有什么问题?

select ...for update语句就是将相应的数据行锁住,但是如果存在幻读,就把for update的语义破坏了。

如何解决幻读?

产生幻读的原因是,行锁只能锁住行,但是新插入记录这个动作,要更新的是记录之间的“间隙”。因此,为了解决幻读问题,InnoDB只好引入新的锁,也就是间隙锁(Gap Lock)。间隙锁和行锁合称 next-key lock , 每个next-key lock是前开后闭区间 。

总结


名称栏目:linux提权命令ch,linux提权方式
浏览路径:http://jkwzsj.com/article/dsgghde.html

其他资讯