mysql幻读怎么样 mysql 幻读

mysql查询的时候怎么解决脏读 , 幻读问题3). 幻读 :
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改 , 这种修改涉及到表中的全部数据行 。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据 。那么 , 以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行 , 就好象发生了幻觉一样 。例如,一个编辑人员更改作者提交的文档 , 但当生产部门将其更改内容合并到该文档的主复本时 , 发现作者已将未编辑的新材料添加到该文档中 。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中 , 则可以避免该问题 。
mysql可重复读的幻读解决方案 首先需要明确的就是“幻读”概念: 隔离级别是可重复读,在一个事务中前后两次查询,查到了其他事务insert进来的数据 。
强调的是读取到了其他事务插入进来的数据 。
下面来论证一下可重复读下幻读的解决方案
先明确一下 , for update语法就是当前读,也就是查询当前已经提交的数据,并且是带悲观锁的 。没有for update就是快照读,也就是根据readView读取的undolog中的数据 。
如果按照以上猜想,那么整个执行结果就违背了 可重复读 的隔离级别了 。
那么我们再假设select * from TABLE where d = 5 for update;这条语句锁定的是所有被扫描到的数据 。
这是因为T2阶段的update会被阻塞?。?毕竟所有被扫描到的记录都被锁定了 。
按照上述推理过程,很显然,即使锁定所有扫描到的数据行 , 也依然存在幻读的情况 。违背了 可重复读 的隔离级别 。
针对这个情况,我们要解决幻读的问题,那么就要求针对所有被扫描的记录行以及还不存在的d=5的记录行都给锁住 。
至此,当前查询结果完全满足 可重复读 的隔离级别 。
通过以上推论,我们可以总结一下,在可重复读的隔离级别下,解决幻读除了需要锁定所有扫描到的记录行外,还需要锁定行之间的间隙,也就是通过间隙锁来解决幻读的问题 。
mysql如何解决幻读幻读是指:在一个事务中,读取到了其他已经提交的事务插入的数据行 。
MySQL在解决脏读、不可重复的读时候,使用了MVCC一致性视图,同时配合行锁来解决 。
至于幻读的解决方式,MySQL引入了临键锁,通过间隙锁可以避免在两个行之间插入数据,从而避免了一个事务在读取的过程中,读取到其他事务插入的数据行 。
正确理解MYSQL的幻读一、定义
1、幻读MYSQL官方叫法是Phantom Rows , 意为鬼影行或者幻影行,请看官方定义:
The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a [ SELECT ] is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.
翻译一下:
所谓的幻影行问题是指,在同一个事务中,同样的查询语句执行多次,得到了不同的行结果集 。
例如 , 如果同一个SELECT语句执行了两次,第二次执行的时候比第一次执行时多出一行,则该行就是所谓的幻影行 。
2、幻读与不可重复读的区别
从官方的定义来看,幻读的定义侧重于多条记录,就是记录条数的变化,而不可重复读侧重于单条记录数据的变化,这样区分原因在于解决幻读需要范围锁,解决不可重复读只需要单条记录加锁
二、InnoDB的REPEATABLE READ级别
InnoDB支持由SQL1992标准描述的所有四个事务隔离级别 , 默认隔离级别是 REPEATABLE READ 。
1、快照读:
在RR模式下,第一次读取会建立快照 , 后续查询会读取快照 。
这意味着,如果在同一事务中发出多个普通[ SELECT ](非锁定)语句,则这些 [ SELECT ]语句的结果也是一致的 。
2、[locking reads](锁定读?。?又叫当前读)
[ SELECT ]语句中使用 FOR UPDATE 或 FOR SHARE
3、行锁
在RR模式下 , 使用当前读以及 [ UPDATE ]和 [ DELETE ]语句会对数据记录加行锁,锁定范围取决于该语句使用的是具有唯一搜索条件的唯一索引还是范围类型搜索条件 。
三、InnoDB的READ COMMITTED级别
1、在RC模式下,每次读取都会刷新快照,因此不能保证可重复读
2、在RC模式下 , 使用当前读以及 [ UPDATE ]和 [ DELETE ]语句会对数据记录加行锁,但是不会加范围锁,间隙锁定仅用于外键约束检查和重复键检查 。
3、由于禁用了间隙锁定 , 因此可能会产生幻影行问题,因为其他会话可以在间隙中插入新行 。
4、 对于[ UPDATE ]或 [ DELETE ]语句,InnoDB 仅对其更新或删除的行持有锁 。MySQL评估 WHERE 条件后 , 将释放不匹配行的记录锁。这大大降低了死锁的可能性,但是仍然可以发生 。
5、对于[ UPDATE ]语句,如果某行已被锁定,则 InnoDB执行“半一致”读取,将最新提交版本的数据返回给MySQL,以便MySQL可以确定该行是否符合WHERE 条件 。如果该行匹配(必须更新),则MySQL会再次读取该行,这一次 InnoDB 会将其锁定或等待获取锁 。
6、注意
从MySQL 8.0.22开始,DML操作(增删改 , 通过联接列表或子查询)从MySQL授权表中读取数据,但不对其进行修改,无论隔离级别如何,都不会在MySQL授权表上获得读取锁 。
有关更多信息,请参见Grant Table Concurrency。
四、乐观锁与悲观锁
1、乐观锁
在UPDATE的WHERE子句中加入版本信息来确定修改是否生效
使用乐观锁时仍然需要非常谨慎,因为RR是可重复读的,在UPDATE之前读取版本号 , 应该使用[当前读],不能使用[快照读]
2、悲观锁
在UPDATE执行前,SELECT后面加上FOR UPDATE来给记录加锁,保证记录在UPDATE前不被修改 。SELECT ... FOR UPDATE是加上了X锁 , 也可以通过SELECT ... LOCK IN SHARE MODE加上S锁,来防止其他事务对该行的修改 。
3、无论是乐观锁还是悲观锁 , 使用的思想都是一致的,那就是当前读 。乐观锁利用当前读判断是否是最新版本,悲观锁利用当前读锁定行 。
五、总结
1、RC级别没有范围锁一定会导致不可重复读和幻影行
2、RR级别安全性更高,实现可重复读的方式为快照,如果需要最新数据可以选择[当前读] , 因此RR级别是首选
3、不论RR还是RC级别,增、删、改的操作都会进行一次[当前读]操作 , 以此获取最新版本的数据,并检测是否有重复的索引 。
4、RR级别下,当前事务如果未发生更新操作(增删改) , 快照版本会保持不变,多次查询读取的快照是同一个
5、RR级别下,当前事务如果发生更新(增删改),会刷新快照 , 会导致不可重复读和幻影行
6、RR级别下,使用当前读,会刷新快照,会导致不可重复读和幻影行
7、RR级别下,可以通过提交当前事务并在此之后发出新查询来为查询获取更新的快照 。
8、RR级别可以部分解决不可重复读和幻读问题
9、其实问题的关键是你的业务逻辑需要可重复读还是最新数据
Mysql:RR隔离级别下的幻读众所周知,Mysql在InnoDB下有四种隔离级别:
未提交读(Read Uncommitted)
提交后读(Read Committed)
可重复读(Repeatable Read)
串行化(Serializable)
其中可重复读(RR)可以避免脏读( a事务读到b事务回滚前的数据)以及可不重复读( a事务在b事务修改提交的前后 , 两次分别读到的数据不一致) 。但是对于幻读(a事务在b事务insert提交前后,两次分别读到的数据不一致),却存在争议 。
下面我们来做一个试验:
对于下面这张简单的数据表
idnum
111
222
333
我们开启a、b两个事务
a事务b事务
beginbegin
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事务
beginbegin
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幻读怎么样 mysql 幻读】mysql幻读怎么样的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于mysql 幻读、mysql幻读怎么样的信息别忘了在本站进行查找喔 。

    推荐阅读