天天看點

FAQ系列 | 修改事務隔離級别的暗門0、導讀1、調整事務隔離級别2、實驗示範3、建議

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

set transaction isolation level SERIALIZABLE;

+----------------+

| @@tx_isolation |

| READ-COMMITTED |

這種方式調整完後,可以看到隔離級别還是RC

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多秒

目前連接配接再次啟動新事務測試
可以看到隔離級别還是RC

update t set d = 20 where a = 1;

Query OK, 1 row affected (0.00 sec)

立即完成,沒有阻塞

其中,測試表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;

3、建議

如果需要全局調整事務隔離級别,最好是在 my.cnf 全局配置檔案中直接設定好。

而如果是要在目前會話中臨時調整,可以不要加上 SESSION 關鍵字,這樣的話,目前事務結束下一個新事務開始後,會自行恢複 SESSION 的設定,無需人為調整,更加友善。