优秀设计赏析网站,网站静态和动态区别是什么,广州工商注册咨询,青岛网站优化价格#x1f4da; Java事务隔离问题详解#xff1a;脏读、不可重复读与幻读#xff08;含解决方案#xff09; 数据库事务是保障数据正确性与一致性的核心机制#xff0c;而隔离性则决定了并发情况下事务是否会“互相干扰”。在事务并发执行时#xff0c;我们可能会遇到三种经… Java事务隔离问题详解脏读、不可重复读与幻读含解决方案 数据库事务是保障数据正确性与一致性的核心机制而隔离性则决定了并发情况下事务是否会“互相干扰”。在事务并发执行时我们可能会遇到三种经典问题脏读Dirty Read、不可重复读Non-repeatable Read 和 幻读Phantom Read。本篇将以通俗易懂的方式讲清楚三者的区别、产生的根源并给出详细的解决方案与数据库隔离级别对应关系。 一、三大并发问题对比
问题类型定义关键特征脏读Dirty Read读取了其他事务尚未提交的数据读到的是“脏”的、可能会被回滚的数据不可重复读Non-repeatable Read同一事务中两次查询同一条记录结果却不同数据在两次查询间被他人修改幻读Phantom Read同一事务中两次查询满足条件的多行数据集合结果行数不同数据在两次查询间被插入或删除 1️⃣ 脏读Dirty Read 什么是脏读
脏读是指一个事务读取了另一个尚未提交事务所修改的数据。
这种情况下如果修改数据的事务最终回滚了那么读取事务中保留的数据就变成了“脏数据” —— 它从未真正存在过。 例子
T1: UPDATE account SET balance 0 WHERE id 1;--未提交T2: SELECT balance FROM account WHERE id 1;
→ 得到余额 0T1: ROLLBACK;T2 读到的值被回滚了等于读到了一个不存在的版本。
️ 解决方案 使用隔离级别Read Committed读已提交或更高 不允许读取未提交的数据Oracle 默认就是 Read CommittedMySQL 的默认 InnoDB 引擎也支持配置为该级别。 2️⃣ 不可重复读Non-repeatable Read 什么是不可重复读
不可重复读是指在同一个事务中读取同一条记录前后结果不一致。
这是因为在两次读取之间另一事务修改并提交了该记录。 例子
T1: SELECT balance FROM account WHERE id 1;
→ 第一次读到 balance 100T2: UPDATE account SET balance 0 WHERE id 1;COMMIT;T1: SELECT balance FROM account WHERE id 1;
→ 第二次读到 balance 0T1 两次读到的值不一样造成了读取不可重复。
️ 解决方案 使用隔离级别Repeatable Read可重复读或更高 保证同一事务中多次读取同一行数据一致在 MySQL InnoDB 中依赖 MVCC多版本并发控制来实现这一点。 3️⃣ 幻读Phantom Read 什么是幻读
幻读是指在一个事务中两次查询相同条件的数据集合但第二次的结果包含了第一次没有的数据行这些新数据是在事务执行期间被其他事务插入的。
幻读是多行数据集合层面的“不可重复读”。 例子
T1: SELECT * FROM employee WHERE salary 1000;
→ 返回 5 条记录T2: INSERT INTO employee (name, salary) VALUES (Tom, 2000);COMMIT;T1: SELECT * FROM employee WHERE salary 1000;
→ 返回 6 条记录多了一条这种新“冒出来的”记录就是“幻影”一样称为幻读。
️ 解决方案 在 Oracle 中 使用隔离级别Serializable串行化 所有并发事务都排队执行能完全避免幻读但性能下降明显。 在 MySQL InnoDB 中 在隔离级别Repeatable Read 下通过 间隙锁Gap Lock 来防止幻读 它不仅锁住已存在的行还锁住“插入的可能区间”因此能避免新记录插入从而防止幻读。 四、数据库隔离级别与三大问题的对应关系
隔离级别脏读不可重复读幻读Read Uncommitted读未提交❌可能❌可能❌可能Read Committed读已提交✅防止❌可能❌可能Repeatable Read可重复读✅防止✅防止✅部分防止MySQL 防止Serializable串行化✅防止✅防止✅完全防止 注意
MySQL 的 InnoDB 引擎在 Repeatable Read 下使用 MVCC 间隙锁能有效防止幻读Oracle 必须使用 Serializable 才能避免幻读 ✅ 五、总结与建议
问题类型典型表现建议隔离级别脏读读到了未提交的修改Read Committed不可重复读同一条记录前后不一致Repeatable Read幻读查询结果行数发生变化Serializable或 InnoDB RR 记忆口诀 脏读别人还没提交我就偷着读不可重复读同一行不一样幻读行数不一样多出来一个“幽灵”。 关于数据库的隔离级别 事务一致性和隔离性的配合使用是保证系统稳定的根本。开发过程中我们需要根据业务对“性能”和“数据安全”的权衡合理选择事务隔离级别避免潜在的数据异常问题。
如果你觉得这篇文章对你有帮助不妨点个、收藏起来也欢迎转发给正在学数据库事务的朋友