MySQL数据库的脏读不可重复读幻读问题

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL数据库的脏读不可重复读幻读问题相关的知识,希望对你有一定的参考价值。

准备

先在数据库种执行select @@tx_isolation命令查看当前数据库的隔离级别。

mysql数据库的默认隔离级别是REPEATABLE-READ,隔离级别就是数据库为了解决脏读、不可重复读和幻读问题的。

为了能够演示脏读、不可重复读和幻读,我们要先修改数据库的隔离级别,否则无法成功演示。

MySQL数据库有如上几种隔离级别,先将隔离级别修改为最低的READ UNCOMMITED,在这种隔离级别下,脏读、不可重复读和幻读的问题都会出现。

使用set tx_isolation='READ-UNCOMMITTED';命令修改隔离级别为最低的READ UNCOMMITED读未提交。

并且执行set autocommit=0取消事务的自动提交。

再准备这样一张表:

脏读

脏读的模拟过程:建立两个MySQL会话,分别为T1和T2,先在两个会话中查看account表的内容,都是一致的;接着在T2会话中执行一条UPDATE语句,对表中username为'lisi'的account字段进行了修改,但没有执行commit语句提交事务,这时候在T2会话中查看表的记录,是正确的,但在其他会话T1中查看表的记录已经是修改后的记录,如果这时候我们对这条username为'lisi'的记录进行操作,但恰巧T2会话回滚了刚才的操作,那么T1会话所做的事情都将会失效,因为这是错误的数据,这也就是脏读问题。

脏读:对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的内容就是临时且无效的。

那么如何解决脏读问题呢?MySQL数据库专门为解决这些问题提出了隔离级别,现在将隔离级别提升到READ COMMITED读取已提交,就能够解决脏读问题了。

执行set tx_isolation='READ-COMMITTED';命令修改隔离级别为READ COMMITED读已提交来解决脏读问题,在修改隔离级别后还需要执行commit;命令,因为刚才已经关闭了事务的自动提交,所以需要手动提交修改。注意:要回滚到'lisi'的account为1000,否则后面不方便查看。

再执行刚才的SQL操作,发现脏读问题已经被解决。

不可重复读

不可重复读模拟过程:在T1和T2会话中查看account表的数据是否为初始状态,然后在T1会话中查看username为'zhangsan'的字段的记录,接着在T2会话中对username为'zhangsan'的字段进行修改并且commit提交事务,再在T1会话中查看username为'zhangsan'的字段的记录,发现它们的account字段的值不一致,这就是发生了不可重复读问题,会造成不良的影响。

不可重复读:有两个事务T1和T2,T1先读取某个字段,然后T2对这个字段进行修改提交后,T1再读这个字段发现值不一样了。

如果要解决不可重复读问题,需要继续提升隔离级别。

执行set tx_isolation='REPEATABLE-READ';命令修改隔离级别为REPEATABLE READ可重复读来解决不可重复读问题,在修改隔离级别后还需要执行commit;命令,因为刚才已经关闭了事务的自动提交,所以需要手动提交修改。注意:要回滚到'lisi'的account为1000,否则后面不方便查看。

再执行刚才的SQL操作,发现脏读问题已经被解决。

只有当在T1会话中commit提交后才能看到已经在T2会话中更新的数据。

幻读

幻读过程模拟:先在1会话中查看记录条数,接着在T2会话中执行插入操作并进行commit提交,最后在T1会话中执行UPDATE操作,本来受影响的行数应该是2行,但实际上却是4行,这就是产生了幻读。

幻读:有两个事务T1和T2,T1先读取表,然后T2在该表中插入一些新行,此时T1再读同一个表,会发现多出来几行。

要解决幻读问题,需要将隔离级别调到SERIALIZABLE,执行set tx_isolation='SERIALIZABLE';命令修改隔离级别为SERIALIZABLE串行化来解决幻读问题,在修改隔离级别后还需要执行commit;命令,因为刚才已经关闭了事务的自动提交,所以需要手动提交修改。注意:要回滚到'lisi'的account为1000,否则后面不方便查看。

再执行刚才的SQL操作,发现脏读问题已经被解决。

只有当T1会话执行commit提交后才能进行操作:

总结

隔离级别就是为了解决脏读、不可重复读、幻读问题的。

隔离级别是否解决脏读是否解决不可重复读是否解决幻读
READ UNCOMMITED×××
READ COMMITED××
REPEATABLE READ×
SERIALIZABLE

以上是关于MySQL数据库的脏读不可重复读幻读问题的主要内容,如果未能解决你的问题,请参考以下文章

数据库中的脏读幻读和不可重复读

MySQL理论:脏读不可重复读幻读

MySQL理论:脏读不可重复读幻读

数据库脏读不可重读读幻读

[MySQL]对于事务并发处理带来的问题,脏读不可重复读幻读的理解与数据库事务隔离级别 - 分析脏读 & 不可重复读 & 幻读

什么是脏读不可重复读幻读?一文带你搞定MySQL事务隔离级别