MySQL提供四种事务隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE,分别解决脏读、不可重复读和幻读等并发问题。其中REPEATABLE READ为InnoDB默认级别,通过MVCC和间隙锁机制在保证一致性的同时兼顾性能,能有效避免大多数幻读场景。可通过SET TRANSACTION在会话级临时调整,或通过配置文件、SET GLOBAL在全局级设置,默认修改需权衡一致性与并发性能,通常建议保持默认并在特定场景下会话级调整。

MySQL控制事务的隔离级别主要通过两种方式:在会话级别使用SET TRANSACTION语句临时调整,或者在服务器级别通过配置文件或SET GLOBAL语句设置默认值。这其实是数据库系统为了在数据一致性和并发性能之间找到平衡点,提供给开发者和DBA的一项关键能力。理解并恰当地设置它,对应用的稳定性和效率都至关重要。
要控制MySQL事务的隔离级别,你可以选择在会话层面或者全局层面进行设置。
在当前会话中设置隔离级别,该设置只对当前客户端连接有效:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- 或者 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 或者 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- 或者 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
这句命令需要在START TRANSACTION之前执行,否则对当前已开始的事务无效,但会影响之后开启的事务。
如果你想为所有新连接设置默认的隔离级别,可以在服务器启动时通过配置文件my.cnf(或my.ini)指定,或者在运行时使用SET GLOBAL语句。
在my.cnf中添加或修改:
[mysqld] transaction-isolation = READ-COMMITTED
注意,这里隔离级别的名称是连字符形式。修改配置文件后需要重启MySQL服务才能生效。
在运行时全局设置(影响之后所有新建立的连接):
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
这会立即影响所有新建立的会话,但不会改变当前已连接会话的隔离级别。对于已连接的会话,它们会继续沿用各自当前的隔离级别,除非它们自己用SET TRANSACTION显式修改。
我个人觉得,虽然有多种设置方式,但日常开发中,我们更多地是依赖MySQL的默认REPEATABLE READ,并在少数需要更高并发
或更高一致性的场景下,才考虑在会话级别进行微调。全局修改默认值则需要更谨慎的评估,因为它会影响整个数据库的行为模式。
MySQL,特别是InnoDB存储引擎,提供了四种标准的事务隔离级别,每种级别都在处理并发问题上有所侧重。理解这些级别以及它们解决的“读现象”是至关重要的。
READ UNCOMMITTED (读未提交)
READ COMMITTED (读已提交)
AI Surge Cloud
低代码数据分析平台,帮助企业快速交付深度数据
87
查看详情
REPEATABLE READ (可重复读)
SELECT语句的幻读问题,但对于UPDATE或DELETE操作,幻读仍有可能发生,需要特定的锁机制来完全避免。SERIALIZABLE (串行化)
REPEATABLE READ隔离级别是如何工作的?它真的能完全避免幻读吗?MySQL的REPEATABLE READ隔离级别之所以能做到“可重复读”,并且在大部分情况下避免幻读,主要归功于InnoDB存储引擎的MVCC(Multi-Version Concurrency Control,多版本并发控制)机制。
当一个事务在REPEATABLE READ级别下启动时,它会获得一个快照(snapshot)。这个快照记录了当前数据库中所有已提交事务的状态。之后,在这个事务的生命周期内,所有的SELECT语句都将基于这个快照来读取数据。这意味着,即使其他事务在此期间修改并提交了数据,当前事务的SELECT操作看到的仍然是它自己快照时刻的数据,从而避免了“不可重复读”。
对于幻读,情况稍微复杂一点。标准的SQL定义中,REPEATABLE READ是允许幻读的。但在MySQL的InnoDB中,MVCC对于SELECT语句的幻读问题提供了强大的缓解。如果一个事务在REPEATABLE READ级别下执行SELECT * FROM table WHERE id > 100;,即使另一个事务插入了id=101的记录并提交,当前事务再次执行同样的SELECT语句,它仍然不会看到id=101这条新记录,因为新记录是在快照之后插入的。
然而,MVCC并不能完全阻止所有形式的幻读,尤其是在涉及数据修改(INSERT, UPDATE, DELETE)的场景。例如,如果一个事务执行了SELECT ... FOR UPDATE或者UPDATE ... WHERE ...,它可能需要锁定一个范围的数据。为了防止其他事务在这个范围内插入新的数据导致“幻影行”,InnoDB会使用间隙锁(Gap Lock)。间隙锁是InnoDB特有的一种锁,它锁定的是索引记录之间的“间隙”,或者锁定某个索引记录之前/之后的间隙。通过锁定这些间隙,可以有效阻止其他事务在被锁定范围内插入新的记录,从而避免了UPDATE或DELETE操作可能导致的幻读。
所以,虽然REPEATABLE READ理论上可能出现幻读,但MySQL InnoDB的实现结合了MVCC和间隙锁,使得它在绝大多数情况下,无论是SELECT还是UPDATE/DELETE,都能提供一个非常接近SERIALIZABLE级别的无幻读体验。这也就是为什么它是MySQL的默认隔离级别,因为它在性能和数据一致性之间找到了一个很好的平衡点。
修改MySQL的默认REPEATABLE READ隔离级别,通常是出于对并发性能或数据一致性更极致的追求。这是一个典型的权衡问题,没有银弹。
考虑降级到 READ COMMITTED 的场景:
READ COMMITTED可以显著提升数据库的并发性能。因为在这个级别下,事务在读取数据时不会像REPEATABLE READ那样持有旧版本快照,而是读取最新的已提交数据。这减少了MVCC的开销,也避免了REPEATABLE READ可能因间隙锁导致的死锁或等待。READ COMMITTED可以提供更好的读取性能,减少锁等待。考虑升级到 SERIALIZABLE 的场景:
SERIALIZABLE可以确保数据在整个事务过程中不会被其他事务修改,从而简化了逻辑,避免了潜在的数据错误。取舍分析:
SERIALIZABLE虽然性能差,但在一定程度上简化了开发,因为它帮你处理了所有并发问题。READ COMMITTED通常只使用行锁,而REPEATABLE READ会结合使用行锁和间隙锁,SERIALIZABLE则可能使用表锁或更严格的行锁。这直接影响了数据库的并发能力。总而言之,修改默认隔离级别是一个需要深思熟虑的决策。我个人的经验是,如果不是有明确的性能瓶颈且确认REPEATABLE READ是瓶颈所在,或者有极其严格的数据一致性需求,通常会选择保持MySQL的默认设置。在需要时,针对特定事务在会话级别进行调整,是一个更安全、更灵活的做法。
以上就是mysql如何控制事务的隔离级别的详细内容,更多请关注其它相关文章!
相关文章:
狙击外星人小游戏开始_狙击外星人小游戏立即开始
微信语音通话掉线如何解决 微信语音通话稳定优化方法
c++项目目录结构应该如何组织_c++工程化项目结构规范
PHP教程:高效从URL路径中提取倒数第二个片段
NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略
神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正
Walmart退货API集成指南:PHP cURL实现与常见问题解析
在J*a中如何开发简易仓库管理与库存统计_仓库管理库存统计项目实战解析
快手极速版在线观看 官方网页版登录地址
sublime怎么进行远程开发编辑_配置rsub/rmate实现sublime编辑服务器文件
Go语言中的*string:深入理解字符串指针
12306选座如何查看座位示意图_12306座位示意图解读与使用
yy漫画网页版官方入口_yy漫画官网登录页面链接
Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】
必由学官方平台入口 必由学在线课堂登录地址
天猫双十一预售商品怎么退款_天猫双十一预售退款操作指南
Golang如何使用context实现超时取消_Golang context超时取消模式实践
深入理解J*aScript Promise异步执行与微任务队列
Angular中单选按钮的正确使用与常见陷阱解析
如何使 Jest 模拟函数默认抛出错误以提高测试效率
抖音从哪里进入网页版_抖音官方入口链接
支付宝如何管理隐私设置_支付宝隐私保护的配置技巧
UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】
Typer应用中动态命令行参数的解析与处理
如何将HTML表格多行数据保存到Google Sheets
mc.js免安装版 mc.js一键畅玩入口
Go语言实现持久化与原子性文件存储的教程
c++中的std::basic_string的SSO优化_c++短字符串优化深度解析
美团外卖商家服务中心入口 美团商家版官网入口
React Router v6 教程:构建认证保护的私有路由与重定向策略
如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!
J*aScript中在Map循环中检测并处理空数组元素
J*a实现学校排课程序_面向对象结构化项目示例
汽水音乐车机版8.9下载 汽水音乐车机版8.9版本安装入口
C++如何操作注册表_Windows平台下C++读写注册表的API函数详解
Angular Material 垂直步进器:实现底部到顶部排序的教程
深入理解J*aScript中的B样条曲线与节点向量生成
Win10桌面图标出现小盾牌怎么办 Win10去除UAC图标教程【解决】
微信网页版登录教程_微信网页版登录入口在哪
Yii2模块参数配置指南:正确声明与访问模块级配置
如何将一个大型PHP应用拆分为多个Composer包_微服务与模块化架构的Composer实践
深入理解Go语言中的指针类型:以*string为例
漫蛙Manwa2官网入口地址分享 漫蛙漫画PC版永久访问通道
抖音小游戏合成大西瓜免费秒玩入口链接 抖音小游戏热门合集秒玩网站
Linux如何构建多环境配置管理_Linux多环境配置方案
Python:递归比较文件夹内容并找出特定类型文件的差异
必由学官方登录入口 必由学教师学生账号快速访问
小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口
抖音怎么赚钱_抖音创作者变现方法与途径指南
初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解