修改事務隔離級別的暗門

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 的設置,無需人爲調整,更加方便。

相關文章
相關標籤/搜索