天天看點

Mysql 死鎖

http://www.cnblogs.com/benshan/archive/2013/05/09/3068886.html

 聲明:以下讨論隻是針對InnoDB存儲引擎。

何為死鎖?

死鎖是對資源的配置設定和使用不當而造成的。是兩個程序争奪某一資源而出現互相等待的現象。具體的來講,出現死鎖需要滿足四個必要條件:

(1)互斥條件:每一個資源都隻能被一個程序使用

(2)請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放

(3)不剝奪條件:程序已獲得的資源,在末使用完之前,不能強行剝奪。

(4)循環等待條件:若幹程序之間形成一種頭尾相接的循環等待資源關系。

很顯然,出現死鎖需要兩個或者兩個以上的程序,換句話說,死鎖發生在并發的程式中。在Mysql中,由于目前隻有InnoDB引擎使用事務(InnoDB支援鎖),便有了InnoDB和死鎖的曠世基情。

死鎖的檢測

1、通過使用Show innodb status檢查引擎狀态 ,可以看到哪些語句産生deadlock

2、MySQL提供了一個information_schema,通過檢視innodb_locks、innodb_trx、innodb_lock_waits這幾個表檢測死鎖。

因循環等待條件而産生的死鎖隻有可能是四種形式:兩張表兩行記錄交叉申請互斥鎖、同一張表則存在主鍵索引鎖沖突、主鍵索引鎖與非聚簇索引鎖沖突、鎖更新導緻的鎖等待隊列阻塞。

死鎖避免

1.如果使用insert…select語句備份表格且資料量較大,在單獨的時間點操作,避免與其他sql語句争奪資源,或使用select into outfile加上load data infile代替 insert…select,這樣不僅快,而且不會要求鎖定

2. 一個鎖定記錄集的事務,其操作結果集應盡量簡短,以免一次占用太多資源,與其他事務處理的記錄沖突。

3.更新或者删除表格資料,sql語句的where條件都是主鍵或都是索引,避免兩種情況交叉,造成死鎖。對于where子句較複雜的情況,将其單獨通過sql得到後,再在更新語句中使用。

4. sql語句的嵌套表格不要太多,能拆分就拆分,避免占有資源同時等待資源,導緻與其他事務沖突。

5. 對定點運作腳本的情況,避免在同一時間點運作多個對同一表進行讀寫的腳本,特别注意加鎖且操作資料量比較大的語句。

6.應用程式中增加對死鎖的判斷,如果事務意外結束,重新運作該事務,減少對功能的影響。