Mysql的事務與鎖知識 三 之 死鎖

2021-10-25 14:18:42 字數 3236 閱讀 5119

在我們使用鎖的時候,有乙個問題是需要注意和避免的,我們知道,排它鎖有互斥的特性。乙個事務或者說乙個執行緒持有鎖的時候,會阻止其他的執行緒獲取鎖,這個時候會造成阻塞等待,如果迴圈等待,會有可能造成死鎖。

這個問題我們需要從幾個方面來分析,一是鎖為什麼不釋放,第二是被阻塞了怎麼辦,第三是死鎖是怎麼發生的,怎麼避免。

鎖什麼時候釋放?

事務結束(commit, rollback);客戶端連線斷開。

如果乙個事務一直未釋放鎖,其他事務會被阻塞多久?會不會永遠等待下去?如果是,在併發訪問比較高的情況下,如果大量事務因無法立即獲得所需的鎖而掛起,會占用大量計算機資源,造成嚴重效能問題,甚至拖跨資料庫。

mysql有乙個引數來控制獲取鎖的等待時間,預設是50秒。

對於死鎖,是無論等多久都不能獲取到鎖的,這種情況,也需要等待50秒鐘嗎?那不是白白浪費了 50秒鐘的時間嗎?

我們先來看一下什麼時候會發生死鎖。

死鎖演示

案例1:

session 1

session 2

begin;

select * from t2 where id =1 for update;

begin;

delete from t2 where id =4 ;

update t2 set name= 『4d』 where id =4 ;

delete from t2 where id =1;

案例2:

session 1

session 2

begin;

select * from t1 where id =1 lock in share mode;

begin;

select * from t1 where id =1 lock in share mode;

update t1 set name= 『1a』 where id =1;

update t1 set name= 『1a』 where id =1;

我們看到:在第乙個事務中,檢測到了死鎖,馬上退岀了,第二個事務獲得了鎖, 不需要等待50秒;

[err] 1213 ・ deadlock found when trying to get lock; try restarting transaction
為什麼可以直接檢測到呢?是因為死鎖的發生需要滿足一定的條件,所以在發生死鎖時,innodb —般都能通過演算法(wait-for graph)自動檢測到。

死鎖的產生條件(因為鎖本身是互斥的):

同一時刻只能有乙個事務持有這把鎖;

其他的事務需要在這個事務釋放鎖之後才能獲取鎖,而不可以強行剝奪;

當多個事務形成等待環路的時候,即發生死鎖。

這個也是表鎖是不會發生死鎖的原因,因為表鎖的資源都是一次性獲取的。

session 1

session 2

begin;

lock tables t2 write;

begin;

lock tables t1 write;

lock tables t1 write; // blocked

//0k,上述語句不再阻塞,釋放了 t2的表鎖,獲取到 t1的表鎖

lock tables t2 write;

// ok,獲取到 t2 的表鎖

如果鎖一直沒有釋放,就有可能造成大量阻塞或者發生死鎖,造成系統吞吐量下降, 這時候就要檢視是哪些事務持有了鎖。

首先,show status命令中,包括了一些行鎖的資訊:

show命令是乙個概要資訊。innodb還提供了三張表來分析事務與鎖的情況:

select

*from information_schema.innodb_trx;

--當前執行的所有事務,還有具體的語句

-- 當前出現的鎖

-- 鎖等待對應的關係

更加詳細的鎖資訊,開啟標準監控和鎖監控:

set

global innodb_status_output=on;

setglobal innodb_status_output_locks=

on;

通過分析鎖日誌,找出持有鎖的事務之後呢?

如果乙個事務長時間持有鎖不釋放,可以kill事務對應的執行緒 id,也就是 innodb_trx表中的trx_mysql_thread_id,例如執行kill4,kill7,kill8。

當然,死鎖的問題不能每次都靠kil執行緒來解決,這是治標不治本的行為。我們應該盡量在應用端,也就是在編碼的過程中避免。

有哪些可以避免死鎖的方法呢?

在程式中,操作多張表時,盡量以相同的順序來訪問(避免形成等待環路);

批量操作單張表資料的時候,先對資料進行排序(避免形成等待環路);

申請足夠級別的鎖,如果要運算元據,就申請排它鎖;

盡量使用索引訪問資料,避免沒有 where 條件的操作,避免鎖表;

如果可以,大事務化成小事務;

使用等值查詢而不是範圍查詢查詢資料,命中記錄,避免間隙鎖對併發的影響。

mysql事務與鎖機制 mysql事務與鎖機制

在併發下事務會容易出現的一些問題 資料更新丟失 兩個事務同時操作一條資料,乙個事務因為異常導致資料更新丟失 髒讀 乙個失誤開始讀取了某行資料,另外乙個事務已經更新了此資料但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都被回滾。不可重複讀 乙個事務對同一行資料重複讀取兩次,但是卻得到了不同的...

MYSQL 事務與鎖

事務的特性 acid 原子性一致性 隔離性永續性 通過redolog 和 doublewrite 頁損壞的情況 實現永續性 事務什麼時候開啟 預設自動開啟,自動提交。通過begin 命令顯式開啟事務 通過commit rollback 結束事務。事務的隔離級別 讀未提交 存在的問題 髒讀 不可重複讀...

MySQL原理及優化(三)MySQL事務與鎖詳解

事務是資料庫管理系統執行過程中的乙個邏輯單位,由乙個有限的資料庫操作序列構成。注意 第一,事務是資料庫的最小工作單元,是不可再分的。第二,它可能包含乙個或者一系列的dml語句。原子性 atomicity 不可再分,意味著對資料庫的操作要麼成功,要麼失敗。失敗的時候要進行回滾。原子性,在innodb裡...