死鎖產生
行鎖的具體實現演算法有三種:record lock、gap lock以及next-key lock。
record lock是專門對索引項加鎖;
gap lock是對索引項之間的間隙加鎖;
next-key lock則是前面兩種的組合,對索引項及其之間的間隙加鎖。
只在可重複讀或以上隔離級別下的特定操作才會取得gap lock或next-key lock,在select、update和delete時,除了基於唯一索引的查詢之外,其它索引查詢時都會獲取gap lock或next-key lock,即鎖住其掃瞄的範圍。主鍵索引也屬於唯一索引,所以主鍵索引是不會使用gap lock或next-key lock。
在mysql中,gap lock預設是開啟的,即innodb_locks_unsafe_for_binlog引數值是disable的,且mysql中預設的是rr事務隔離級別。
當執行以下查詢sql時,由於order_no列為非唯一索引,此時又是rr事務隔離級別,所以select的加鎖型別為gap lock,這裡的gap範圍是(4,+∞)。
1 select id from demo.order_record where order_no = 4 for update;
執行查詢sql語句獲取的gap lock並不會導致阻塞,而當執行以下插入sql時,會在插入間隙上再次獲取插入意向鎖。
插入意向鎖其實也是一種gap鎖,它與gap lock是衝突的,所以當其它事務持有該間隙的gap lock時,需要等待其它事務釋放gap lock之後,才能獲取到插入意向鎖。
以上事務a和事務b都持有間隙(4,+∞)的gap鎖,而接下來的插入操作為了獲取到插入意向鎖,都在等待對方事務的gap鎖釋放,於是就造成了迴圈等待,導致死鎖。
1 insert into demo.order_record(order_no, status, create_date) values (5, 1, '2019-08-30 12:22:22');
可以通過以下鎖的相容矩陣圖,來檢視鎖的相容性:
避免死鎖的措施
避免死鎖最直觀的方法就是在兩個事務相互等待時,當乙個事務的等待時間超過設定的某一閾值,就對這個事務進行回滾,另乙個事務就可以繼續執行了。這種方法簡單有效,在innodb中,引數innodb_lock_wait_timeout是用來設定超時時間的。
另外,還可以將order_no列設定為唯一索引列。雖然不能防止幻讀,但可以利用它的唯一性來保證訂單記錄不重複建立,這種方式唯一的缺點就是當遇到重複建立訂單時會丟擲異常。
還可以使用其它的方式來代替資料庫實現冪等性校驗。例如,使用redis以及zookeeper來實現,執行效率比資料庫更佳。
常見死鎖的問題
死鎖的四個必要條件:互斥、占有且等待、不可強佔用、迴圈等待。只要系統發生死鎖,這些條件必然成立。
innodb儲存引擎的主鍵索引為聚簇索引,其它索引為輔助索引。
如果之前使用輔助索引來更新資料庫,就需要修改為使用聚簇索引來更新資料庫。
如果兩個更新事務使用了不同的輔助索引,或乙個使用了輔助索引,乙個使用了聚簇索引,就都有可能導致鎖資源的迴圈等待。由於本身兩個事務是互斥,也就構成了以上死鎖的四個必要條件了。
綜上可知,在更新操作時,應該盡量使用主鍵來更新表字段,這樣可以有效避免一些不必要的死鎖發生。
解決死鎖的最佳方式就是預防死鎖:
在程式設計中盡量按照固定的順序來處理資料庫記錄,假設有兩個更新操作,分別更新兩條相同的記錄,但更新順序不一樣,有可能導致死鎖;
在允許幻讀和不可重複讀的情況下,盡量使用rc事務隔離級別,可以避免gap lock導致的死鎖問題;
更新表時,盡量使用主鍵更新;
避免長事務,盡量將長事務拆解,可以降低與其它事務發生衝突的概率;
設定鎖等待超時引數,可以通過innodb_lock_wait_timeout設定合理的等待超時閾值,特別是在一些高併發的業務中,可以盡量將該值設定得小一些,避免大量事務等待,占用系統資源,造成嚴重的效能開銷。
mysql 壓力 死 MySQL死鎖
死鎖產生 死鎖是指兩個或多個事務在同一資源上相互占用,並請求鎖定對方占用的資源,從而導致惡性迴圈。當事務試圖以不同的順序鎖定資源時,就可能產生死鎖。多個事務同時鎖定同乙個資源時也可能會產生死鎖。檢測死鎖 資料庫系統實現了各種死鎖檢測和死鎖超時的機制。innodb儲存引擎能檢測到死鎖的迴圈依賴並立即返...
mysql沒有事務死鎖 Mysql事務與死鎖
好久沒有寫部落格了,最近工作太忙了,真的是996icu呀。想找個機會跳出來。之後我要做到work life balance!當考慮的就是資料一致性的問題時我們用就應該想到mysql的事務。但是當我們使用事務時會有很多的坑,首先我們了解一下事務的隔離界別。1 事物的隔離級別 資料庫中有四種資料隔離級別...
mysql死鎖後狀態 mysql如何解除死鎖狀態
第一種 前提條件 找到執行非常慢的sql 如何找呢 還原客戶遇到的問題場景,從控制台找到所執行的sql,一句句的去執行,直到找到執行非常慢的sql 1.查詢是否鎖表 show open tables where in use 0 2.查詢程序 如果您有super許可權,您可以看到所有執行緒。否則,您...