MYSQL資料庫事務4種隔離級別及7種傳播行為
事務的特性:
原子性:事務的不可分割,組成事務的各個邏輯單元不可分割。
一致性:事務執行的前後,資料完整性保持一致。
隔離性:事務執行不應該受到其他事務的干擾。
永續性:事務一旦結束,資料就持久化到資料庫中。
檢視/設定隔離級別
檢視:SELECT @@tx_isolation 設定:set tx_isolation='xxx'
事務的隔離級別
如果不考慮隔離性,引發一些安全問題
隔離性:一個事務的執行,不應該受到其他事務的干擾。
髒讀:一個事務讀到了另一個事務未提交的資料,導致查詢結果不一致
不可重複讀:一個事務讀到了另一個事務已經提交的update的資料,導致多次查詢結果不一致。
虛讀/幻讀:一個事務讀到了另一個事務已經提交的insert的資料,導致多次查詢結果不一致。
設定事務的隔離級別:
read uncommitted (讀取未提交內容) :髒讀,不可重複讀,虛讀都有可能發生
read committed (讀取提交內容) :避免髒讀。但是不可重複讀和虛讀是有可能發生
repeatable read (可重讀) :避免髒讀和不可重複讀,但是虛讀有可能發生。
serializable(可序列化) :避免髒讀,不可重複讀,虛讀。
通過例項演示四種隔離級別
read uncommitted (讀取未提交內容) :
事務A:開啟事務並執行 SELECT * FROM testtest, 但並不提交事務
set tx_isolation='read-uncommitted'; start transaction; SELECT * FROM testtest;
結果顯示:
事務B:開始事務並執行 UPDATE testtest set age = 200 WHERE name = 'zhangsan'; 但並不提交事務
start transaction;
UPDATE testtest set age = 200 WHERE name = 'zhangsan';
事務A:再次執行 SELECT * FROM testtest
在事務B未提交的情況下,仍然讀到了修改的200,出現了髒讀!
read committed (讀取提交內容)
事務A:開啟事務並執行 SELECT * FROM testtest, 但並不提交事務
事務B:開始事務並執行 UPDATE testtest set age = 200 WHERE name = 'zhangsan'; 但並不提交事務
start transaction;
UPDATE testtest set age = 200 WHERE name = 'zhangsan';
事務A:再次執行 SELECT * FROM testtest
在事務B未提交的情況下,沒有讀到修改的200,避免了髒讀!
事務B:提交事務。
事務A:再次執行 SELECT * FROM testtest
在事務B提交的情況下,讀到了修改的200,出現了不可重複讀!(同一個事務中多次讀取結果不一致)
repeatable read (可重讀) mysql預設
事務A:開啟事務並執行 SELECT * FROM testtest, 但並不提交事務
事務B:開始事務並執行 UPDATE testtest set age = 200 WHERE name = 'zhangsan'; 但並不提交事務
start transaction;
UPDATE testtest set age = 200 WHERE name = 'zhangsan';
事務A:再次執行 SELECT * FROM testtest
在事務B未提交的情況下,沒有讀到修改的200,避免了髒讀!
事務B:提交事務。
事務A:再次執行 SELECT * FROM testtest
在事務B提交的情況下,沒有讀到修改的200,避免了不可重複讀!
再次 開啟事務B,並新增一條記錄,並提交事務
start transaction;
INSERT INTO testtest(name,age) VALUES ('wangwu','100');
COMMIT;
事務A:再次執行 SELECT * FROM testtest
並沒有讀到新增的記錄
事務A:插入剛才事務B新增的記錄
INSERT INTO testtest(name,age) VALUES ('wangwu','100');
發現插不進去,因為事務B已經新增並提交事務了(我們name欄位做了唯一索引),出現了幻讀!(查詢的時候沒有,但插入的時候確實存在,跟出現幻覺一樣)。
serializable(可序列化)
事務A:開啟事務並執行 SELECT * FROM testtest, 但並不提交事務
start transaction;
SELECT * FROM testtest;
事務B:開始事務並執行 UPDATE testtest set age = 200 WHERE name = 'zhangsan'
發現事務B停在那裡了,沒有任何執行,直到事務A提交事務。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。
傳播行為
1、PROPAGATION_REQUIRED:如果當前沒有事務,就建立一個新事務,如果當前存在事務,就加入該事務,該設定是最常用的設定。
2、PROPAGATION_NESTED:如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作
3、PROPAGATION_SUPPORTS:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。‘
4、PROPAGATION_MANDATORY:支援當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就丟擲異常。
5、PROPAGATION_REQUIRES_NEW:支援當前事務,建立新事務,無論當前存不存在事務,都建立新事務。
6、PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
7、PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則丟擲異常。