Python全栈入门到实战【数据库篇 18】MySQL事务隔离级别详解,并发数据安全的核心控制

发布时间:2026/8/1 6:20:48

Python全栈入门到实战【数据库篇 18】MySQL事务隔离级别详解,并发数据安全的核心控制 前言上一篇《数据库篇 17》中我们已经掌握了事务的基本操作和ACID四大核心特性学会了如何通过事务保证数据的原子性和一致性。本篇作为数据库篇的第十八篇我们将深入讲解事务ACID中的隔离性这是并发数据安全的核心。当多个事务同时操作同一批数据时如果没有适当的隔离机制就会出现脏读、不可重复读、幻读等严重的数据不一致问题。我们将详细讲解这三个并发问题以及MySQL提供的四种事务隔离级别教你如何根据业务需求选择合适的隔离级别。本文为Python全栈开发者与数据库入门者量身打造通过问题定义场景示例实战验证的方式清晰讲解每一个并发问题的产生原因和解决方法每一个隔离级别都有可直接运行的验证代码同时重点标注生产环境中的最佳实践和常见陷阱即使是完全没有并发编程经验的同学也能快速掌握事务隔离级别的核心知识。本节核心学习内容并发事务问题脏读、不可重复读、幻读的定义与场景事务隔离级别四种隔离级别的对比与解决能力隔离级别操作查看与设置会话/全局隔离级别的语法完整实战逐级别验证并发问题的存在与解决常见误区全局与会话隔离、幻读的本质等避坑指南最佳实践生产环境隔离级别的选择原则核心总结并发问题与隔离级别速查表文章目录前言一、并发事务带来的三个问题1.1 脏读1.2 不可重复读1.3 幻读二、MySQL的四种事务隔离级别2.1 隔离级别解决能力对比2.2 查看与设置隔离级别查看当前隔离级别设置隔离级别三、实战演示不同隔离级别的效果验证3.1 准备测试数据3.2 验证读未提交Read uncommitted3.3 验证读已提交Read committed3.4 验证可重复读Repeatable Read3.5 验证串行化Serializable四、常见误区与最佳实践五、核心总结事务并发问题与隔离级别速查表并发问题总结隔离级别总结常用操作语法六、专栏订阅一、并发事务带来的三个问题当多个事务同时访问数据库中的同一批数据时如果数据库没有提供隔离机制就会出现以下三个经典的并发问题导致数据不一致问题描述脏读一个事务读到了另外一个事务还没有提交的数据不可重复读一个事务先后读取同一条记录但两次读取的数据不同幻读一个事务按照条件查询数据时没有对应的行但插入数据时又发现该行已经存在好像出现了幻影1.1 脏读定义一个事务读到了另一个事务未提交的修改数据。场景示例事务A读取张三的账户余额为2000元事务B修改张三的账户余额为1000元但尚未提交事务事务A再次读取张三的账户余额得到1000元读到了事务B未提交的数据事务B回滚张三的账户余额恢复为2000元此时事务A读到的1000元就是脏数据基于此数据的所有操作都是错误的1.2 不可重复读定义在同一个事务内先后两次读取同一条记录得到的结果不同。场景示例事务A读取张三的账户余额为2000元事务B修改张三的账户余额为1000元并提交事务事务A再次读取张三的账户余额得到1000元在同一个事务A中两次读取同一条记录的结果不同这就是不可重复读1.3 幻读定义一个事务按照条件查询数据时没有找到对应的行但当它尝试插入该行数据时又发现该行已经存在好像出现了幻影。场景示例事务A查询id1的用户结果为空事务B插入id1的用户并提交事务事务A尝试插入id1的用户报错主键冲突事务A再次查询id1的用户结果仍然为空在可重复读隔离级别下对于事务A来说id1的用户就像幻影一样看不见但又插不进去二、MySQL的四种事务隔离级别为了解决上述并发问题MySQL提供了四种事务隔离级别隔离级别从低到高依次为Read uncommitted读未提交Read committed读已提交Repeatable Read可重复读MySQL的默认隔离级别Serializable串行化2.1 隔离级别解决能力对比不同的隔离级别可以解决不同的并发问题隔离级别越高数据越安全但性能越低。隔离级别脏读不可重复读幻读Read uncommitted✅✅✅Read committed❌✅✅Repeatable Read默认❌❌✅Serializable❌❌❌✅ 表示存在该问题❌ 表示解决了该问题2.2 查看与设置隔离级别查看当前隔离级别-- MySQL 8.0及以上版本SELECTTRANSACTION_ISOLATION;-- MySQL 5.x版本SELECTtx_isolation;设置隔离级别-- 设置当前会话的隔离级别只对当前连接有效SETSESSIONTRANSACTIONISOLATIONLEVEL{READUNCOMMITTED|READCOMMITTED|REPEATABLEREAD|SERIALIZABLE};-- 设置全局的隔离级别对所有新连接有效已存在的连接无效SETGLOBALTRANSACTIONISOLATIONLEVEL{READUNCOMMITTED|READCOMMITTED|REPEATABLEREAD|SERIALIZABLE};⚠️ 重要注意不要随便修改全局隔离级别这会影响所有连接到数据库的应用。如果需要修改应该只修改当前会话的隔离级别。三、实战演示不同隔离级别的效果验证下面我们通过两个MySQL客户端窗口分别模拟两个并发事务验证不同隔离级别下的并发问题。3.1 准备测试数据-- 创建账户表CREATETABLEaccount(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(20)NOTNULL,moneyDECIMAL(10,2)NOTNULLDEFAULT0);-- 插入测试数据INSERTINTOaccount(name,money)VALUES(张三,2000.00),(李四,2000.00);3.2 验证读未提交Read uncommitted目标验证脏读问题步骤客户端A事务A客户端B事务B1SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;2BEGIN;BEGIN;3SELECT * FROM account WHERE name 张三;结果张三 2000.004UPDATE account SET money 1000 WHERE name 张三;5SELECT * FROM account WHERE name 张三;结果张三 1000.00读到了事务B未提交的数据脏读发生6ROLLBACK;7SELECT * FROM account WHERE name 张三;结果张三 2000.003.3 验证读已提交Read committed目标验证脏读已解决但不可重复读仍然存在步骤客户端A事务A客户端B事务B1SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;2BEGIN;BEGIN;3SELECT * FROM account WHERE name 张三;结果张三 2000.004UPDATE account SET money 1000 WHERE name 张三;5SELECT * FROM account WHERE name 张三;结果张三 2000.00没有读到未提交的数据脏读已解决6COMMIT;7SELECT * FROM account WHERE name 张三;结果张三 1000.00同一个事务内两次读取结果不同不可重复读发生3.4 验证可重复读Repeatable Read目标验证脏读和不可重复读已解决但幻读仍然存在步骤客户端A事务A客户端B事务B1SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;2BEGIN;BEGIN;3SELECT * FROM account WHERE id 3;结果空4INSERT INTO account(id, name, money) VALUES (3, 王五, 3000.00);5COMMIT;6SELECT * FROM account WHERE id 3;结果空可重复读保证了同一个事务内读取结果一致7INSERT INTO account(id, name, money) VALUES (3, 王五, 3000.00);报错Duplicate entry ‘3’ for key ‘PRIMARY’插入失败幻读发生8SELECT * FROM account WHERE id 3;结果仍然为空3.5 验证串行化Serializable目标验证所有并发问题都已解决步骤客户端A事务A客户端B事务B1SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;2BEGIN;BEGIN;3SELECT * FROM account WHERE id 4;结果空4INSERT INTO account(id, name, money) VALUES (4, 赵六, 4000.00);阻塞等待事务A结束5COMMIT;阻塞解除插入成功6SELECT * FROM account WHERE id 4;结果赵六 4000.00没有幻读问题四、常见误区与最佳实践全局与会话隔离级别的区别SESSION级别只对当前连接有效GLOBAL级别对所有新连接有效已存在的连接不受影响。生产环境中永远不要修改全局隔离级别。默认隔离级别的选择MySQL默认的Repeatable Read隔离级别已经解决了脏读和不可重复读问题能够满足绝大多数业务场景的需求不需要修改。串行化的性能问题Serializable隔离级别会将所有事务串行执行性能极差只有在对数据一致性要求极高的场景如金融交易才会使用。幻读的本质幻读不是读不到而是插入失败。MySQL的可重复读隔离级别通过间隙锁Gap Lock在很大程度上解决了幻读问题但不能完全解决。隔离级别与性能的权衡隔离级别越高数据越安全但并发性能越低。应该根据业务对数据一致性的要求选择最低的能够满足需求的隔离级别。五、核心总结事务并发问题与隔离级别速查表为了方便后续开发时快速查阅整理了并发问题与隔离级别的核心速查表并发问题总结问题定义本质脏读读到未提交的数据读取了临时数据不可重复读同一事务内两次读取同一条记录结果不同数据被修改幻读查询不到但插入失败数据被插入隔离级别总结隔离级别解决的问题存在的问题性能适用场景Read uncommitted无脏读、不可重复读、幻读最高几乎不使用Read committed脏读不可重复读、幻读高Oracle、PostgreSQL默认Repeatable Read默认脏读、不可重复读幻读中MySQL默认绝大多数业务场景Serializable所有问题无最低对数据一致性要求极高的场景常用操作语法操作语法查看当前隔离级别SELECT TRANSACTION_ISOLATION;设置会话隔离级别SET SESSION TRANSACTION ISOLATION LEVEL 级别;设置全局隔离级别SET GLOBAL TRANSACTION ISOLATION LEVEL 级别;六、专栏订阅专栏优点《Python从入门到实战》专栏内容涵盖Python基础到高级编程、并发编程进程/线程/协程、网络编程TCP/UDP/Socket、核心内置/第三方模块、数据库核心实战、Web开发Django/Flask/FastAPI框架、数据库MySQL/ORM/异步数据库、网络爬虫同步/异步/分布式、AI实战、Linux部署运维等全栈核心知识以项目驱动教学构建清晰学习路径适合零基础入门和进阶提升的同学跟着一步步从入门到精通专栏地址https://blog.csdn.net/zsh_1314520/category_13108073.html文章是永久吗一次订阅后可永久免费查看专栏内所有文章后续会持续更新全栈相关内容第一时间获取最新教程有答疑交流群吗订阅专栏后有专属的全栈学习答疑群群内提供专业问题答疑、和众多学习者抱团取暖一起沉淀技术、赋能成长进群方式订阅专栏后可直接在专栏内申请加入答疑群或私信博主沟通进群事宜https://bbs.csdn.net/topics/620104702更多干货点赞收藏关注博主不迷路博主博客链接https://blog.csdn.net/zsh_1314520?spm1000.2115.3001.5343专注Python全栈技术分享评论区留言问题会一一回复助力大家轻松搞定Python全栈【原创声明】除本文原文地址以外如发现同款内容皆为盗版本文已收录于《Python全栈从入门到实战》请勿购买盗版文章和专栏如购买盗版内容不提供任何服务。原文地址https://blog.csdn.net/zsh_1314520/article/details/163373625

相关新闻