MySQL中的脏读与幻读使用及说明

 更新时间:2025年08月15日 15:57:02   作者:知识浅谈  
MySQL通过事务隔离级别(如REPEATABLEREAD)和锁机制(共享/排他锁)解决脏读与幻读问题,结合MVCC与Next-KeyLocks优化并发一致性,合理配置可平衡性能与数据可靠性

引言

在数据库事务处理中,**脏读(Dirty Read)幻读(Phantom Read)**是两种常见的数据一致性问题,尤其在多事务并发场景下容易发生。

MySQL通过事务隔离级别和锁机制来解决这些问题。本文将深入探讨这两个问题的本质、实际影响,并提供具体的解决方案。

一、概念解析

1. 脏读(Dirty Read)

定义:事务A读取了事务B未提交的数据,随后事务B回滚,导致事务A读取的数据无效。

示例

-- 事务B
START TRANSACTION;
UPDATE users SET balance = 200 WHERE id = 1; -- 未提交

-- 事务A
START TRANSACTION;
SELECT balance FROM users WHERE id = 1; -- 读到200(脏数据)

若事务B回滚,用户的实际余额仍为原值,但事务A使用了错误的数据。

2. 幻读(Phantom Read)

定义:事务A两次查询同一条件的数据,事务B在期间插入或删除符合条件的数据,导致事务A两次结果集不一致。

示例

-- 事务A
START TRANSACTION;
SELECT * FROM orders WHERE amount > 100; -- 返回5条记录

-- 事务B
INSERT INTO orders (amount) VALUES (200); -- 插入新数据并提交

-- 事务A再次查询
SELECT * FROM orders WHERE amount > 100; -- 返回6条记录(出现幻行)

幻读强调结果集数量的变化,区别于不可重复读(同一行数据的修改)。

二、影响分析

1. 脏读的影响

  • 数据不一致性:读取未提交的中间状态数据,可能导致业务逻辑错误(如错误扣款)。
  • 决策错误:报表系统基于脏数据生成统计结果,影响业务决策。

2. 幻读的影响

  • 数据完整性破坏:重复插入校验可能失效(如唯一约束冲突)。
  • 统计失真:同一事务内多次统计结果不一致,影响分析准确性。

三、解决方案

1. 事务隔离级别

MySQL通过设置不同的事务隔离级别来控制并发问题:

隔离级别脏读不可重复读幻读
READ UNCOMMITTED✔️✔️✔️
READ COMMITTED✖️✔️✔️
REPEATABLE READ✖️✖️✔️
SERIALIZABLE✖️✖️✖️

解决脏读

  • 使用READ COMMITTED或更高级别。

解决幻读

  • MySQL的REPEATABLE READ通过多版本并发控制(MVCC)Next-Key Locks实际可避免大部分幻读。
  • SERIALIZABLE通过强制事务串行执行彻底解决,但性能代价高。

设置隔离级别

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; 

2. 锁机制

  • 共享锁(Shared Lock)SELECT ... LOCK IN SHARE MODE,允许其他事务读但禁止写。
  • 排他锁(Exclusive Lock)SELECT ... FOR UPDATE,禁止其他事务读写。

示例防止幻读

START TRANSACTION;
SELECT * FROM orders WHERE amount > 100 FOR UPDATE; -- 加排他锁
-- 事务B的INSERT操作会被阻塞
COMMIT;

3. 乐观锁(业务层控制)

通过版本号或时间戳实现:

ALTER TABLE orders ADD COLUMN version INT DEFAULT 0;

-- 事务A
START TRANSACTION;
SELECT amount, version FROM orders WHERE id = 1; -- version=1

-- 事务B试图修改时会失败
UPDATE orders SET amount = 200, version = version + 1 
WHERE id = 1 AND version = 1; 

四、实战建议

  1. 默认选择:MySQL默认隔离级别为REPEATABLE READ,在多数场景下平衡性能与一致性。
  2. 高并发写入场景:谨慎使用SERIALIZABLE,优先考虑Next-Key Locks或乐观锁。
  3. 代码规范:在ORM框架(如Hibernate)中显式控制事务边界和锁策略。

五、总结

脏读和幻读的根源在于事务并发与数据可见性。通过合理设置隔离级别、锁机制和业务层控制,可以在性能和数据一致性之间找到平衡。理解不同解决方案的适用场景,是设计高可靠数据库系统的关键。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 浅谈MySQL模糊查询中通配符的转义

    浅谈MySQL模糊查询中通配符的转义

    下面小编就为大家带来一篇浅谈MySQL模糊查询中通配符的转义。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • MySQL DATEDIFF函数获取两个日期的时间间隔的方法

    MySQL DATEDIFF函数获取两个日期的时间间隔的方法

    这篇文章主要介绍了MySQL DATEDIFF函数获取两个日期的时间间隔的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • mysql 8.0.21 安装配置方法图文教程

    mysql 8.0.21 安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.21 安装配置方法图文教程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • mysql中关于between和in的区别

    mysql中关于between和in的区别

    这篇文章主要介绍了mysql中关于between和in的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 一次Mysql使用IN大数据量的优化记录

    一次Mysql使用IN大数据量的优化记录

    这篇文章主要给大家介绍了关于Mysql使用IN大数据量的优化的实战记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • MySQL内部临时表的具体使用

    MySQL内部临时表的具体使用

    MySQL临时表在很多场景中都会用到,比如用户自己创建的临时表用于保存临时数据,以及MySQL内部在执行复杂SQL时,需要借助临时表进行分组、排序、去重等操作,本文就来详细的介绍一下MySQL内部临时表
    2021-10-10
  • mysql数据库重置表主键id的实现

    mysql数据库重置表主键id的实现

    在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,本文主要介绍了mysql数据库重置表主键id的实现,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • MySQL错误:Can‘t connect to MySQL server on localhost解决办法(分多种情况)

    MySQL错误:Can‘t connect to MySQL server on localhost解决办法

    这篇文章主要给大家介绍了关于MySQL错误:Can‘t connect to MySQL server on localhost的解决办法,文中介绍的方法分多种情况,通过代码介绍的非常详细,需要的朋友可以参考下
    2024-05-05
  • mysql设置远程访问数据库的多种方法

    mysql设置远程访问数据库的多种方法

    最近有一同学问我MySQL无法远程访问怎么呢,但能使用localhost来进行方法,下面脚本之家来给各位介绍一下解决办法,需要的朋友可以参考下
    2013-10-10
  • MySQL中DATE_FORMAT时间函数的使用小结

    MySQL中DATE_FORMAT时间函数的使用小结

    本文主要介绍了MySQL中DATE_FORMAT时间函数的使用小结,用于格式化日期/时间字段,可提取年月、统计月份数据、精确到天,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-08-08

最新评论