1. 程式人生 > >MYSQL資料庫事務4種隔離級別及7種傳播行為

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:以非事務方式執行,如果當前存在事務,則丟擲異常。