欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > ”三读四隔“:图解数据库三种读问题与四种事务隔离级别

”三读四隔“:图解数据库三种读问题与四种事务隔离级别

2025/6/21 10:54:09 来源:https://blog.csdn.net/llwszx/article/details/148799909  浏览:    关键词:”三读四隔“:图解数据库三种读问题与四种事务隔离级别

在数据库的并发访问场景中,数据一致性问题始终是开发者需要重点关注的核心。MySQL作为最流行的关系型数据库之一,其事务处理机制中的脏读、不可重复读和幻读问题,以及对应的事务隔离级别,是保障数据一致性的关键技术。本文将通过详细的代码示例、时序图和原理分析,带读者深入理解这些概念。

一、MySQL三种典型读问题详解

1.1 脏读(Dirty Read)

定义:一个事务读取到另一个事务未提交的数据,若后者回滚,前者读到的数据即为"脏数据"。

代码示例

-- 会话A(未提交事务)
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 1;
-- 此时会话B读取到未提交的余额-- 会话B
START TRANSACTION;
SELECT balance FROM account WHERE id = 1;  -- 读取到减少后的余额
COMMIT;-- 会话A
ROLLBACK;  -- 回滚事务,余额恢复

时序图

会话A 会话B 数据库 START TRANSACTION UPDATE account SET balance=900 WHERE id=1 START TRANSACTION SELECT balance FROM account WHERE id=1 返回900(未提交数据) ROLLBACK 事务回滚,余额恢复为1000 COMMIT 数据已提交但实际为脏数据 会话A 会话B 数据库

1.2 不可重复读(Non-repeatable Read)

定义:因为另一个事务修改并提交了该数据,导致一个事务中多次读取同一数据时结果不同。

代码示例

-- 会话A
START TRANSACTION;
SELECT balance FROM account WHERE id = 1;  -- 读取余额1000
-- 会话B修改并提交-- 会话B
START TRANSACTION;
UPDATE account SET balance = balance + 500 WHERE id = 1;
COMMIT;-- 会话A
SELECT balance FROM account WHERE id = 1;  -- 读取余额1500(与第一次不同)
COMMIT;

时序图

会话A 会话B 数据库 START TRANSACTION SELECT balance FROM account WHERE id=1 返回1000 START TRANSACTION UPDATE account SET balance=1500 WHERE id=1 COMMIT 事务提交 SELECT balance FROM account WHERE id=1 返回1500(与第一次不同) COMMIT 会话A 会话B 数据库

1.3 幻读(Phantom Read)

定义:因为另一个事务插入了新数据并提交。一个事务中多次查询结果集不同。

代码示例

-- 会话A
START TRANSACTION;
SELECT * FROM orders WHERE status = '未支付';  -- 结果集有10条记录
-- 会话B插入新记录并提交-- 会话B
START TRANSACTION;
INSERT INTO orders (status) VALUES ('未支付');
COMMIT;-- 会话A
SELECT * FROM orders WHERE status = '未支付';  -- 结果集有11条记录(出现"幻影")
COMMIT;

时序图

会话A 会话B 数据库 START TRANSACTION SELECT * FROM orders WHERE status='未支付' 返回10条记录 START TRANSACTION INSERT INTO orders (status) VALUES('未支付') COMMIT 事务提交,新增1条记录 SELECT * FROM orders WHERE status='未支付' 返回11条记录(出现幻影) COMMIT 会话A 会话B 数据库

二、MySQL四种事务隔离级别详解

2.1 读未提交(Read Uncommitted)

定义:最低隔离级别,允许读取未提交的数据变更。
解决问题:无,会出现脏读、不可重复读、幻读。
实现手段:不使用任何锁,直接读取数据。

时序图

事务A 事务B 数据库 START TRANSACTION UPDATE data SET value=新值 START TRANSACTION SELECT data (无锁直接读取) 返回未提交的新值 ROLLBACK 数据回滚 COMMIT 提交脏数据 事务A 事务B 数据库

2.2 读提交(Read Committed)

定义:只能读取已提交的数据,解决脏读问题。
解决问题:解决脏读,仍存在不可重复读和幻读。
实现手段

  • 读操作:使用共享锁(S锁),读完即释放
  • 写操作:使用排他锁(X锁),提交后释放

时序图

事务A 事务B 数据库 START TRANSACTION UPDATE data SET value=新值(加X锁) START TRANSACTION SELECT data (尝试加S锁,被阻塞) COMMIT (释放X锁) 事务提交 获取S锁,读取已提交数据 COMMIT (释放S锁) 事务A 事务B 数据库

2.3 可重复读(Repeatable Read)

定义:确保同一事务中多次读取结果一致,解决不可重复读。
解决问题:解决脏读、不可重复读,通过MVCC解决部分幻读。
实现手段

  • MVCC(多版本并发控制)
  • 读操作:基于版本号读取历史快照
  • 写操作:使用Next-Key Lock(记录锁+间隙锁)防止幻读

时序图

事务A 事务B 数据库 START TRANSACTION 生成快照版本号V1 SELECT data (基于V1读取) 返回数据版本V1 START TRANSACTION UPDATE data SET value=新值 COMMIT (生成新版本V2) SELECT data (仍基于V1读取) 返回数据版本V1(结果一致) COMMIT 事务A 事务B 数据库

2.4 串行化(Serializable)

定义:最高隔离级别,强制事务串行执行。
解决问题:解决所有读问题(脏读、不可重复读、幻读)。
实现手段

  • 读操作:加共享锁(S锁),直到事务结束
  • 写操作:加排他锁(X锁),直到事务结束
  • 所有事务按顺序执行

时序图

事务A 事务B 数据库 START TRANSACTION SELECT data (加S锁) START TRANSACTION UPDATE data (尝试加X锁,被阻塞) COMMIT (释放S锁) 事务提交 获取X锁,执行更新 COMMIT (释放X锁) 事务A 事务B 数据库

三、隔离级别与读问题对照表

隔离级别脏读不可重复读幻读核心解决方案时序特点
读未提交无锁,直接读取未提交数据
读提交读锁读完释放,写锁提交释放,阻止脏读
可重复读MVCC快照读+Next-Key Lock阻止幻读
串行化读写锁持续到事务结束,强制事务串行执行

四、MySQL隔离级别实现细节

4.1 可重复读(默认级别)解决幻读的关键机制

事务A 事务B 数据库 START TRANSACTION SELECT * FROM orders WHERE id>10 (加Next-Key Lock) 返回结果集 START TRANSACTION INSERT INTO orders (id) VALUES(11) (被间隙锁阻塞) COMMIT (释放锁) 事务提交 执行插入操作 COMMIT 事务A 事务B 数据库

4.2 MVCC多版本并发控制流程

事务A 数据库 START TRANSACTION 分配版本号V1 SELECT data (读取版本V1) 返回V1版本数据 其他事务更新数据,生成V2版本 SELECT data (仍读取V1) 返回V1版本数据(结果一致) 事务A 数据库

五、如何选择合适的隔离级别

  1. 读未提交:适用于临时统计查询,对数据一致性要求极低的场景,存在读取脏数据风险,需谨慎使用。
  2. 读提交:适合大多数互联网应用(如电商订单查询),避免脏读且性能较好。
  3. 可重复读:MySQL默认隔离级别,适用于金融交易、库存管理等对一致性要求较高的场景,通过MVCC和间隙锁解决大部分并发问题。
  4. 串行化:适用于对一致性要求极高的场景(如银行转账),但性能开销较大,可能导致大量锁等待。

通过上述的详细解析,相信能帮助读者对MySQL的并发读问题和事务隔离级别有了更深入的理解。在实际开发中,应根据业务场景的特点,合理选择事务隔离级别,在数据一致性和系统性能之间找到最佳平衡点。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词