在上篇博客中我有提到过MySQL Inoodb引擎中的四大隔离级别,详细 点击打开链接
隔离级别分别为:
1.读未提交(read-uncommitted) 2.读已提交(read-committed) 3.可重复读(repeatable-read) 4.串行化(serializable);
下面我将对 ‘脏’读,不可重复读,幻读进行详细的介绍和各种隔离级别如何解决问题,以便于读者更深入了理解四个隔离级别的意义
一、脏读
(一)问题:
打开客户端A,B设置隔离级别成 读未提交(read-uncommited),数据库默认级别是 可重复读(repeatable-read)。当前两个客户端的隔离级别设置成了 读未提交。如图1-1
图1-1
第一步:客户端A更新数据 如图1-2
图1-2
第二步:客户端B查看数据 如图1-3
图1-3
第三步:客户端A回滚 当前数据库的记录 value=1,而客户端B读到的数据 value=2 如图1-4
图1-4
(二)解决:MySQL应对策略-读已提交 (read-committed)
已经设置客户端A,B的隔离级别未读已提交
第一步:客户端A更新 value=1->value=2 如图2-1
图2-1
第二步:客户端B读取数据 如图2-2
图2-2
第三步:客户端A提交,此时客户端B再查询数据 数据才生效,因此 读已提交 解决了脏读的问题 如图2-3,2-4
图2-3
图2-4
二、不可重复读
(一)问题:
客户端A,B此时的隔离级别都是读已提交
第一步:客户端A第一次读取数据 如图3-1
图3-1
第二步:客户端B更新数据 value=2 如图3-2
图3-2
第三步:客户端A第二次查询数据 第二次读取到的数据与第一次不一致,造成了不可重复读
如图3-3
图3-3
(二)MySQL应对策略-可重复读
客户端A,B设置隔离级别为可重复读
第一步:客户端A读取数据 如图4-1
图4-1
第二步:客户端B更新数据value=1 如图4-2
图4-2
第三步:客户端A第二次读取数据,value=2 值没有变换,所以避免了不可重复读的问题 如图4-3
如图4-3
三、幻读
(一)问题:
当前客户端A,B的隔离级别是可重复读
第一步:客户端A 查询数据 如图5-1,可知表中不存在id=2的数据
图5-1
第二步:客户端B在表中插入id=2的数据 如图5-2
图5-2
第三步:客户端A在表中插入id=2的数据,如图5-3,可见数据库报错,客户端A原本以为数据id=2的记录不存在,想要添加时候却发现 记录又存在了,就像‘幻影’一样,这就是幻读
如图5-3
(二)解决:MySQL应对策略-串行化(serialiable),主要加入了 next-key locks,具体的加锁过程可看:点击打开链接
设置客户端A,B的隔离级别为串行化(serialiable)
第一步:客户端A查询数据 如图6-1 不存在数据id=3的记录
图6-1
第二步:客户端B添加id=3的记录 如图6-2 出现了等待锁超时的情况 添加失败,只有等客户端A释放了锁之后,客户端B才能添加记录,因此解决了幻读的问题。
图6-2