在我們使用鎖的時候,有乙個問題是需要注意和避免的,我們知道,排它鎖有互斥的特性。乙個事務或者說乙個執行緒持有鎖的時候,會阻止其他的執行緒獲取鎖,這個時候會造成阻塞等待,如果迴圈等待,會有可能造成死鎖。
這個問題我們需要從幾個方面來分析,一是鎖為什麼不釋放,第二是被阻塞了怎麼辦,第三是死鎖是怎麼發生的,怎麼避免。
鎖什麼時候釋放?
事務結束(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裡...