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 的設定,無需人為調整,更加友善。