資料庫 隔離級別,鎖基礎,一致性鎖定 非鎖定 讀

2021-08-03 23:39:03 字數 4474 閱讀 1817

隔離級別相關語句

1.檢視當前會話隔離級別

select @@tx_isolation;

2.檢視系統當前隔離級別

select @@global.tx_isolation;

3.設定當前會話隔離級別

set session transaction isolation level repeatable read;

4.設定系統當前隔離級別

set global transaction isolation level repeatable read;

5.命令列,開始事務時

set autocommit=off 或者 start transaction

查詢事務或鎖的相關語句

檢視正在鎖的事務

select * from information_schema.innodb_locks;

檢視等待鎖的事務

select * from information_schema.innodb_lock_waits;

查詢 正在執行的事務:

select * from information_schema.innodb_trx;

鎖的兩個基本型別

共享鎖【s鎖】

又稱讀鎖,若事務t對資料物件a加上s鎖,則事務t可以讀a但不能修改a,其他事務只能再對a加s鎖,而不能加x鎖,直到t釋放a上的s鎖。這保證了其他事務可以讀a,但在t釋放a上的s鎖之前不能對a做任何修改。

排他鎖【x鎖】

又稱寫鎖。若事務t對資料物件a加上x鎖,事務t可以讀a也可以修改a,其他事務不能再對a加任何鎖,直到t釋放a上的鎖。這保證了其他事務在t釋放a上的鎖之前不能再讀取和修改a。

各隔離級別詳解(以下場景均指事務執行過程中)

read uncommitted(讀取未提交內容)

read committed(讀取提交內容)

repeatable read(可重讀)(mysql預設事務隔離級別)

serializable(可序列化)

這四種隔離級別採取不同的鎖型別來實現,若讀取的是同乙個資料的話,就容易發生問題。例如:

在mysql中,實現了這四種隔離級別,分別有可能產生問題如下所示:

可以在cmd中使用mysql指令,模擬併發事務的場景。

mysql -u root -p
一致性非鎖定讀(顧名思義,只針對select)

在事務隔離級別rc和rr下,innodb儲存引擎引擎使用非鎖定的一致性讀。在這種預設的讀取方式下,才能呈現上節中各種隔離級別產生的場景。

一致性非鎖定讀(consistent nonlocking read)是指innodb儲存引擎通過多版本控制(multi versionning)的方式來讀取當前執行時間資料庫中行的資料,如果讀取的行正在執行delete或update操作,這時讀取操作不會因此等待行上鎖的釋放。相反的,innodb會去讀取行的乙個快照資料。

然而,對於快照資料的定義卻不相同。在rc事務隔離級別下,對於快照資料,非一致性讀總是被鎖定行的最新乙份快照資料。而在rr事務隔離級別下,對於快照資料,非一致性讀總是讀取事務開始時的行資料版本。

上面展示了innodb儲存引擎一致性的非鎖定讀。之所以稱為非鎖定讀,因為不需要等待訪問的行上x鎖的釋放

多版本控制

快照資料是指該行之前版本的資料,該實現是通過undo段來完成。而undo用來事務中的回滾資料,因此快照資料本身沒有額外的開銷。這裡可以理解為既然undo日誌包括了所有用來恢復歷史版本資料的資訊,那麼我們只要將「不同版本」指標指向不同時間節點的undo日誌即可。此外,讀取快照資料不需要上鎖,因為沒有事務需要對歷史資料進行修改操作。

一致性鎖定讀

如果乙個事務希望在讀取的時候就把記錄鎖住,不允許其他事務進行修改應該怎麼做呢?那就是select … for update,select … for update顯式地給一條記錄加x鎖,因此其他事務不能獲取該記錄的任何鎖。我們也可以使用select … lock in share mode來給記錄顯式地加s鎖,因此其他事務能夠獲取該記錄的s鎖而不能獲取該記錄的x鎖,這兩種語句都是有特定的應用場景的。

注意:for update和in share mode字尾,只能和select語句搭配使用

(x鎖和任何鎖都不相容,s鎖和s鎖可以相容)

一些場景(但不是傳統意義上的幻讀)

1.rc和rr模式下,當其中乙個執行緒往資料庫中新增了主鍵,但並沒有commit時(※),另一線程若嘗試新增同樣的記錄,則會提示超時。

error 1205 (hy000): lock wait timeout exceeded; try restarting transaction

2.rr模式下會出現的幻讀情況

t session a                   session b

|| start

transaction;

start

transaction;

|| select * from t_bitfly;

| empty set

| insert

into t_bitfly

| values (1, 'a');

|| select * from t_bitfly;

| empty set

| commit;

|| select * from t_bitfly;

| empty set

|| insert

into t_bitfly values (1, 'a');

| error 1062 (23000):

| duplicate entry '1' for key 1

v (****, 剛剛明明告訴我沒有這條記錄的)

t session a                  session b

|| start

transaction;

start

transaction;

|| select * from t_bitfly;

| +------+-------+

| | id | value |

| +------+-------+

| | 1 | a |

| +------+-------+

| insert

into t_bitfly

| values (2, 'b');

|| select * from t_bitfly;

| +------+-------+

| | id | value |

| +------+-------+

| | 1 | a |

| +------+-------+

| commit;

|| select * from t_bitfly;

| +------+-------+

| | id | value |

| +------+-------+

| | 1 | a |

| +------+-------+

|| update t_bitfly set

value='z';

| rows matched: 2 changed: 2 warnings: 0

| (怎麼多出來一行)

|| select * from t_bitfly;

| +------+-------+

| | id | value |

| +------+-------+

| | 1 | z |

| | 2 | z |

| +------+-------+

|

一致性非鎖定讀讀取的仍然是同乙個快照版本,即舊的版本。

在同乙個事務中,我們不是select,而用update,就會查到資料,因為此時沒有使用一致性非鎖定讀,select對應的是舊快照的版本,而update修改的卻是最新的版本

rr模式下避免幻讀

innodb提供了next-key locks,但需要應用程式自己去加鎖。

select * from child where id > 100

forupdate;

一致性非鎖定讀和一致性鎖定讀

在預設配置下innodb的隔離級別是repeatable read,innodb的select操作使用的是一致性非鎖定讀 一致性的非鎖定行讀 consistent nonlocking read,簡稱cnr 是指innodb儲存引擎通過行多版本控制 multi versioning 的方式來讀取當前...

一致性非鎖定讀與一致性鎖定讀

一致性非鎖定讀 consistent nonlocking read 是指innodb儲存引擎通過 行多版本控制 multi versioning 的方式來讀取當前執行時間資料庫中行的資料。如果讀取的行正在執行delete或update操作,這時讀取操作不會因此去等待行上鎖的釋放,相反地,innod...

資料庫一致性

資料庫一致性 database consistency 是指事務執行的結果必須是使資料庫從乙個一致性狀態變到另乙個一致性狀態。保證資料庫一致性是指當事務完成時,必須使所有資料都具有一致的狀態。在關係型資料庫中,所有的規則必須應用到事務的修改上,以便維護所有資料的完整性。保證資料庫的一致性是資料庫管理...