3 回答

TA貢獻1830條經驗 獲得超9個贊
正如在有關此問題的眾多SO線程之一中提到的那樣:有時鎖定表的進程顯示為在進程列表中睡眠!我正在撕扯我的頭發,直到我殺死所有在相關數據庫中打開的睡眠線程(當時沒有一個是活躍的)。最終解鎖了表并讓更新查詢運行。
這位評論者說了一句類似于“有時一個MySQL線程會鎖定一個表,然后在等待與MySQL無關的事情發生時休眠?!?/p>
在重新審核show engine innodb status日志之后(一旦我跟蹤了負責鎖定的客戶端),我發現有問題的卡住線程列在事務列表的最底部,位于即將發生錯誤的活動查詢下方由于凍結鎖定:
------------------
---TRANSACTION 2744943820, ACTIVE 1154 sec(!!)
2 lock struct(s), heap size 376, 2 row lock(s), undo log entries 1
MySQL thread id 276558, OS thread handle 0x7f93762e7710, query id 59264109 [ip] [database] cleaning up
Trx read view will not see trx with id >= 2744943821, sees < 2744943821
(不確定“Trx讀取視圖”消息是否與凍結鎖相關,但與其他活動事務不同,此消息不會顯示已發出的查詢,而是聲稱事務處于“清理”狀態,但具有多個行鎖)
故事的寓意是,即使線程處于休眠狀態,事務也可以處于活動狀態。

TA貢獻1784條經驗 獲得超2個贊
由于MySQL的普及,難怪鎖定等待超時; 嘗試重啟事務異常得到如此多的關注SO。
您擁有的爭用越多,死鎖的可能性就越大,數據庫引擎將通過暫停其中一個死鎖事務來解決這個問題。此外,已修改(例如UPDATE
或DELETE
)大量條目(如“ 高性能Java持久性”一書中所述,它采用鎖以避免臟寫異常)的長時間運行事務更有可能與其他事務產生沖突。
雖然InnoDB MVCC,您仍然可以使用該FOR UPDATE
子句請求顯式鎖。但是,與其他流行的數據庫(Oracle,MSSQL,PostgreSQL,DB2)不同,MySQL 使用REPEATABLE_READ
默認的隔離級別。
現在,您獲取的鎖(通過修改行或使用顯式鎖定)將在當前運行的事務期間保留。如果你想之間的差異的一個很好的解釋REPEATABLE_READ
,并READ COMMITTED
在問候鎖定,請閱讀這篇文章的Percona。
在REPEATABLE READ中,在事務期間保持的每個鎖都在事務期間保持。
在READ COMMITTED中,在STATEMENT完成后釋放與掃描不匹配的鎖。
...
這意味著在READ COMMITTED中,一旦UPDATE語句完成,其他事務可以自由更新它們無法更新的行(在REPEATABLE READ中)。
隔離級別越嚴格(REPEATABLE_READ
,SERIALIZABLE
),死鎖的可能性就越大。這不是一個“本身”的問題,這是一個權衡。
您可以獲得非常好的結果READ_COMMITED
,因為在使用跨越多個HTTP請求的邏輯事務時,您需要應用程序級丟失更新防護。在樂觀鎖定方法的目標丟失更新,如果你使用的是甚至可能發生SERIALIZABLE
隔離級別,同時通過允許您使用減少了鎖爭用READ_COMMITED
。
添加回答
舉報