修改事务隔离级别的暗门

0、导读

咱们知道,MySQL里能够动态修改事务隔离级别(TRANSACTIOIN ISOLATION LEVEL),既能够加 GLOBAL 关键字直接修改全局的设置,也能够加 SESSION 关键字只修改当前会话的设置。那么,若是两个关键字都不加,会出现什么状况呢?html

一、调整事务隔离级别

MySQL里,能够直接用 SET 指令调整事务隔离级别,既能够对全局调整,也能够只调整当前会话,其用法见下:mysql

SET [GLOBAL | SESSION] TRANSACTIONsql

[ REPEATABLE READsession

| READ COMMITTEDapp

| READ UNCOMMITTED测试

| SERIALIZABLE ]spa

咱们都知道指定 GLOBAL 关键字是能够修改全局的设置,用这个方式修改完后,已经存在的链接还不会生效,只有对新创建的链接才会起做用。orm

而指定 SESSION 关键字则是只修改当前链接会话的设置,修改完后当即生效,再次链接后会恢复成全局的设置,对其余链接/会话也不起做用。htm

另外,若是都不指定 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中原先的设置

二、实验演示

为了证明上面的说法,咱们能够作一个演示,详细过程见下:

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 |
+—+—+—+—+

三、建议

若是须要全局调整事务隔离级别,最好是在 my.cnf 全局配置文件中直接设置好。

而若是是要在当前会话中临时调整,能够不要加上 SESSION 关键字,这样的话,当前事务结束下一个新事务开始后,会自行恢复 SESSION 的设置,无需人为调整,更加方便。

相关文章
相关标签/搜索