MySQL事务隔离级别解决脏读 不可重复读 幻读问题

冷不防 2022-05-21 09:45 380阅读 0赞

在上篇博客中我有提到过MySQL Inoodb引擎中的四大隔离级别,详细 点击打开链接

隔离级别分别为:

1.读未提交(read-uncommitted) 2.读已提交(read-committed) 3.可重复读(repeatable-read) 4.串行化(serializable);

下面我将对 ‘脏’读,不可重复读,幻读进行详细的介绍和各种隔离级别如何解决问题,以便于读者更深入了理解四个隔离级别的意义

一、脏读

(一)问题:

打开客户端A,B设置隔离级别成 读未提交(read-uncommited),数据库默认级别是 可重复读(repeatable-read)。当前两个客户端的隔离级别设置成了 读未提交。如图1-1

70

图1-1

第一步:客户端A更新数据 如图1-2

70 1

图1-2

第二步:客户端B查看数据 如图1-3
  1. ![70 2][]

图1-3

第三步:客户端A回滚 当前数据库的记录 value=1,而客户端B读到的数据 value=2 如图1-4

70 3

图1-4

(二)解决:MySQL应对策略-读已提交 (read-committed)

  1. 已经设置客户端A,B的隔离级别未读已提交

第一步:客户端A更新 value=1->value=2 如图2-1

  1. ![70 4][]

图2-1

第二步:客户端B读取数据 如图2-2

70 5

图2-2

第三步:客户端A提交,此时客户端B再查询数据 数据才生效,因此 读已提交 解决了脏读的问题 如图2-3,2-4

70 6

图2-3

70 7

图2-4

二、不可重复读

(一)问题:

客户端A,B此时的隔离级别都是读已提交 第一步:客户端A第一次读取数据 如图3-1

70 8

图3-1

第二步:客户端B更新数据 value=2 如图3-2

70 9

图3-2

第三步:客户端A第二次查询数据 第二次读取到的数据与第一次不一致,造成了不可重复读

如图3-3

70 10

图3-3

(二)MySQL应对策略-可重复读

客户端A,B设置隔离级别为可重复读

第一步:客户端A读取数据 如图4-1

70 11

图4-1

第二步:客户端B更新数据value=1 如图4-2

70 12

图4-2

第三步:客户端A第二次读取数据,value=2 值没有变换,所以避免了不可重复读的问题 如图4-3

70 13

如图4-3

三、幻读

(一)问题:

当前客户端A,B的隔离级别是可重复读

第一步:客户端A 查询数据 如图5-1,可知表中不存在id=2的数据

70 14

图5-1

第二步:客户端B在表中插入id=2的数据 如图5-2

70 15

图5-2

第三步:客户端A在表中插入id=2的数据,如图5-3,可见数据库报错,客户端A原本以为数据id=2的记录不存在,想要添加时候却发现 记录又存在了,就像‘幻影’一样,这就是幻读

70 16

如图5-3

(二)解决:MySQL应对策略-串行化(serialiable),主要加入了 next-key locks,具体的加锁过程可看:

设置客户端A,B的隔离级别为串行化(serialiable)

第一步:客户端A查询数据 如图6-1 不存在数据id=3的记录

70 17

图6-1

第二步:客户端B添加id=3的记录 如图6-2 出现了等待锁超时的情况 添加失败,只有等客户端A释放了锁之后,客户端B才能添加记录,因此解决了幻读的问题。

70 18

图6-2

以上言论,仅供学习使用,希望大家有不同看法的留言给我,谢谢大家。

发表评论

表情:
评论列表 (有 0 条评论,380人围观)

还没有评论,来说两句吧...

相关阅读