专业的编程技术博客社区

网站首页 > 博客文章 正文

MySQL篇:可重复读(Repeatable Read)隔离级别可以解决幻读吗?

baijin 2025-02-19 10:50:20 博客文章 14 ℃ 0 评论

幻读是MySQL数据库数据一致性可能存在的问题,是指在一个事务内,第一次查询的结果记录集为N,第二次相同条件的查询结果集>N,好像幽灵一样出现之前查询未有之记录。出现幻读现象,可以推理出在读事务期间,其他事务增加并提交了记录,并在读事务中体现出来。

如何解决幻读呢?MySQL已经为我们提供了解决方案,那就是可重复读(Repeatable Read)隔离级别。通常认为可重复读(Repeatable Read)隔离级别是可以解决幻读问题的,但实际情况却与你想象的不太一致。

MySQL为了通常情况下可以解决,但是存在特殊情况。

通常情况下:

1-1、查询数据库的隔离级别:

1-2、打开两个数据连接,分别开启事务T1和T2

1-3、在T1和T2两个事务中查询:select * from user;查询结果一致。

1-4、T1事务中执行insert语句:INSERT INTO `user` VALUES (5, 'e', 18);

在T1事务中执行查询语句,查询结果包含新插入的记录;

1-5、在T2事务中执行查询语句,查询结果不包含未提交的T1事务中插入的记录:

1-6、T1提交之后,T2事务中再执行查询语句,依然是不包含T1事务中插入的记录,达到不可重复读的隔离效果。

1-7、T2事务提交之后,再执行查询语句,T1已提交事务插入的记录,包含在查询结果中。

特殊情况下:

2-1、查询数据库的隔离级别:

2-2、打开两个数据连接,分别开启事务T1和T2

2-3、在T1和T2两个事务中查询:select * from user;查询结果一致。

2-4、T1事务中执行insert语句:INSERT INTO `user` VALUES (5, 'e', 18);

在T1事务中执行查询语句,查询结果包含新插入的记录;

2-5、在T2事务中执行查询语句select * from user for update;,出现死锁等待现象:

2-6、T1提交之后,T2事务中再执行查询语句select * from user for update;,却包含T1事务中插入的记录,没有达到不可重复读的隔离效果,出现幻读。

2-7、T1事务提交之后,T2事务中再执行查询语句select * from user;,依然是不包含T1事务中插入的记录,达到不可重复读的隔离效果。

2-8、T2事务提交之后,再执行查询语句,T1已提交事务插入的记录,包含在查询结果中。

总结

如果要彻底的解决幻读的问题,必须采用MySQL数据库的最高隔离级别串行化 (SERIALIZABLE),也就是所有的操作都是顺序的 、加锁的,但是这样会严重降低MySQL的性能,在平衡幻读与性能的基础上,MySQL默认的隔离策略是可重复读(Repeatable Read)。

其实任何的策略都是为了业务服务的,脱离业务谈策略,都是不切实际的幻想,MySQL数据库也是为业务服务的,也需要遵循这一原则。




本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表