Mysql

MySQL:事務和死鎖

  • February 25, 2018

我有表“tbl_data”,其中有很多行(3-5 百萬)。

我有 JAVA (*.jar) 模組,我從中將數據插入/更新到此表中。

如果我啟動 *.jar 文件(例如,“run.jar”)並在 INSERT/UPDATE 過程之後按順序啟動“run.jar”,則沒有問題 - 工作正常。

如果我啟動“run.jar”,然後啟動“run_01.jar”(具有類似邏輯的 jar 文件:INSERT/UPDATE into “tbl_data”),我會得到錯誤:

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:嘗試獲取鎖時發現死鎖;嘗試重啟事務

“run.jar”中的所有操作都在事務中執行,例如:

開始交易;
插入 tbl_data …;
更新 tbl_data …;
犯罪;

因此,我需要能夠同時從多個來源進行 INSERT/UPDATE 而不會阻止表進行修改(每個 jar 文件 UPDATES/INSERTS 在“tbl_data”中都有自己的行,因此修改數據中的數據沒有問題時間)。

如果您完全確定數據的隔離狀態,您可以將全域隔離級別設置為READ COMMITTED甚至READ UNCOMMITTED。索引中的第一個塊較少,在您的情況下應該足夠了。第二個安排所有SELECT語句都是非阻塞的。這是盡可能低的。

REPEATABLE READ無論您選擇什麼,您都應該在插入數據後立即將全域隔離級別設置回。

global意味著這適用於所有已建立的連接。因此,此更改也會影響jar文件旁邊的連接。如果您有可能更改jar文件,則應在兩個文件中使用SESSION關鍵字設置基於連接的隔離級別。jar

查看完整的錯誤消息很重要。它應該提到鎖定索引的名稱。如果是主鍵或唯一索引,多個事務嘗試同時插入相同的值。如果是這種情況,您應該修復此行為。

如果是非唯一索引,問題是鎖的粒度不夠(間隙鎖)。我建議:

  • 設置 innodb_lock_wait_timeout = 0
  • 每次收到錯誤1205(一行被鎖定),重試事務

即使您不遵循我的建議,在發生死鎖的情況下,重試合理次數(1?)也是一個好主意。因為,即使您的程序遵循所有最佳實踐,有時您可能仍會看到死鎖。

引用自:https://dba.stackexchange.com/questions/61859