MySQL事务隔离级别的暗门
0、导读
我们知道,MySQL里可以动态修改事务隔离级别(TRANSACTIOIN ISOLATION LEVEL),既可以加 GLOBAL 关键字直接修改全局的设置,也可以加 SESSION 关键字只修改当前会话的设置。那么,如果两个关键字都不加,会出现什么情况呢?
1、调整事务隔离级别
MySQL里,可以直接用 SET 指令调整事务隔离级别,既可以对全局调整,也可以只调整当前会话,其用法见下:
SET [GLOBAL | SESSION] TRANSACTION
[ REPEATABLE READ
| READ COMMITTED
| READ UNCOMMITTED
| SERIALIZABLE ]
我们都知道指定 GLOBAL 关键字是可以修改全局的设置,用这个方式修改完后,已经存在的连接还不会生效,只有对新建立的连接才会起作用。
而指定 SESSION 关键字则是只修改当前连接会话的设置,修改完后立即生效,再次连接后会恢复成全局的设置,对其他连接/会话也不起作用。
另外,如果都不指定 GLOBAL、SESSION 关键字,会发生什么情况呢?官方文档给出的解释是这样的:
Without any SESSION or GLOBAL keyword, the statement applies to the next (not started) transaction performed within the current session. Subsequent transactions revert to using the SESSION isolation level.
原文详见手册:13.3.6 SET TRANSACTION Syntax,出处链接:https://dev.mysql.com/doc/refman/5.6/en/set-transaction.html
意思是说:采用这种方式设置后,本次连接当前事务还未起作用,要到下一个(尚未启动的)新事务才起作用,下一个事务结束后,又将恢复成本次 SESSION中原先的设置。
2、实验演示
为了证实上面的说法,我们可以做一个演示,详细过程见下:
T1 | T2 |
select @@tx_isolation; READ-COMMITTED | select @@tx_isolation; READ-COMMITTED |
set transaction isolation level SERIALIZABLE; select @@tx_isolation; +—————-+ | @@tx_isolation | +—————-+ | READ-COMMITTED | 这种方式调整完后,可以看到隔离级别还是RC | |
select @@tx_isolation; READ-COMMITTED | |
begin; select * from t; | a | b | c | d | +—+—+—+—+ | 1 | 2 | 3 | 4 | | |
begin; select * from t; | a | b | c | d | +—+—+—+—+ | 1 | 2 | 3 | 4 | update t set d = 5 where a = 1; 被阻塞了,耐心等待中~ | |
rollback; | |
Query OK, 1 row affected (13.13 sec) Rows matched: 1 Changed: 1 Warnings: 0 等到T1执行rollback后才能继续,等了10多秒 | |
rollback; | |
当前连接再次启动新事务测试 | |
select @@tx_isolation; READ-COMMITTED 可以看到隔离级别还是RC | |
select @@tx_isolation; READ-COMMITTED | |
begin; select * from t; | a | b | c | d | +—+—+—+—+ | 1 | 2 | 3 | 4 | | |
begin; select * from t; | a | b | c | d | +—+—+—+—+ | 1 | 2 | 3 | 4 | | |
update t set d = 20 where a = 1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 立即完成,没有阻塞 | |
rollback; | |
rollback; |
其中,测试表t的建表DDL:
CREATE TABLE `t` (
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`,`b`),
KEY `i_c` (`c`)
) ENGINE=InnoDB;
该表中只有一条记录:
SELECT * FROM t;
+—+—+—+—+
| a | b | c | d |
+—+—+—+—+
| 1 | 2 | 3 | 4 |
+—+—+—+—+
3、建议
如果需要全局调整事务隔离级别,最好是在 my.cnf 全局配置文件中直接设置好。
而如果是要在当前会话中临时调整,可以不要加上 SESSION 关键字,这样的话,当前事务结束下一个新事务开始后,会自行恢复 SESSION 的设置,无需人为调整,更加方便。
建议继续学习:
- 分布式系统的事务处理 (阅读:5968)
- 分布式事务性能分析 (阅读:3853)
- MySQL数据库分布式事务XA优缺点与改进方案 (阅读:3557)
- 关于sqlite的事务的使用 (阅读:2714)
- Google Megastore系统事务机制 (阅读:2361)
- MySQL数据库分布式事务XA的实现原理分析 (阅读:2272)
- Storm入门教程 第五章 一致性事务 (阅读:1897)
- 深入剖析 redis 事务机制 (阅读:1554)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:叶金荣 来源: iMySQL
- 标签: 事务 隔离
- 发布时间:2016-02-29 23:57:29
- [66] Go Reflect 性能
- [65] Oracle MTS模式下 进程地址与会话信
- [64] 如何拿下简短的域名
- [59] android 开发入门
- [59] IOS安全–浅谈关于IOS加固的几种方法
- [58] 图书馆的世界纪录
- [58] 【社会化设计】自我(self)部分――欢迎区
- [53] 视觉调整-设计师 vs. 逻辑
- [47] 界面设计速成
- [46] 读书笔记-壹百度:百度十年千倍的29条法则