慕斯王
2019-08-06 13:54:44
如何避免mysql'試圖鎖定時發現死鎖; 嘗試重啟事務'我有一個innoDB表記錄在線用戶。它會在用戶每次刷新頁面時更新,以跟蹤他們所在的頁面以及他們上次訪問網站的日期。然后,我有一個每15分鐘運行一次以刪除舊記錄的cron。我得到了一個'試圖鎖定時發現的死鎖; 嘗試重新啟動事務'昨晚約5分鐘,似乎是在這個表中運行INSERT。有人可以建議如何避免這個錯誤?===編輯===以下是正在運行的查詢:首次訪問網站:INSERT INTO onlineusers SETip = 123.456.789.123,datetime = now(),userid = 321,page = '/thispage',area = 'thisarea',type = 3在每個頁面刷新:UPDATE onlineusers SETips = 123.456.789.123,datetime = now(),userid = 321,page = '/thispage',area = 'thisarea',type = 3WHERE id = 888Cron每15分鐘一次:DELETE FROM onlineusers WHERE datetime <= now() - INTERVAL 900 SECOND然后它會記錄一些統計數據(即:在線成員,在線訪客)。
3 回答

四季花海
TA貢獻1811條經驗 獲得超5個贊
可以幫助解決大多數死鎖的一個簡單技巧是按特定順序對操作進行排序。
當兩個事務試圖以相反的順序鎖定兩個鎖時,你會遇到死鎖,即:
連接1:鎖定鍵(1),鎖定鍵(2);
連接2:鎖定鍵(2),鎖定鍵(1);
如果兩者同時運行,則連接1將鎖定密鑰(1),連接2將鎖定密鑰(2),并且每個連接將等待另一個連接釋放密鑰 - >死鎖。
現在,如果您更改了查詢,連接將以相同的順序鎖定密鑰,即:
連接1:鎖定鍵(1),鎖定鍵(2);
連接2:鎖定鍵(1),鎖定鍵(2);
陷入僵局是不可能的。
所以這就是我的建議:
除了delete語句之外,確保沒有其他任何鎖定訪問多個密鑰的查詢。如果你這樣做(我懷疑你這樣做),請按升序排列他們的WHERE(k1,k2,.. kn)。
修復delete語句以升序工作:
更改
DELETE FROM onlineusers WHERE datetime <= now() - INTERVAL 900 SECOND
至
DELETE FROM onlineusers WHERE id IN (SELECT id FROM onlineusers WHERE datetime <= now() - INTERVAL 900 SECOND order by id) u;
另外要記住的是mysql文檔建議在遇到死鎖的情況下,客戶端應該自動重試。您可以將此邏輯添加到客戶端代碼中。(比如,在放棄之前對此特定錯誤進行3次重試)。

慕桂英3389331
TA貢獻2036條經驗 獲得超8個贊
delete語句很可能會影響表中總行數的很大一部分。最終,這可能會導致在刪除時獲取表鎖。持有鎖(在這種情況下是行鎖或頁鎖)并獲得更多鎖定始終是一種死鎖風險。但是我無法解釋為什么insert語句導致鎖升級 - 它可能與頁面拆分/添加有關,但是更好地了解MySQL的人必須填寫那里。
首先,可以嘗試立即為delete語句顯式獲取表鎖。
添加回答
舉報
0/150
提交
取消