2009-08-20 86 views
9

我們有一個(目前InnoDB)表,其中包含大約500,000行。這表示要運行的任務隊列。它存儲在一個MySQL數據庫中。MySQL刪除行上的死鎖

一個持續的基礎,至少每秒一次,但有時更頻繁,我們從中選擇數據並隨後更新一些行。我們每天一次修剪表格中的舊行。

我們開始在桌上發現死鎖,這導致我們的任務處理陷入停滯。這些僵局是在夜間修剪過程中造成的。 DELETE,SELECT和UPDATE的組合意味着基本上沒有什麼生產力可能發生。我不幸沒有SHOW ENGINE INNODB STATUS的輸出。

我想知道處理這個問題的最佳選擇。請注意,我們的代碼檢測到死鎖並重新發出查詢。另外,我們很久以前發現,一次刪除所有匹配的行對於看到很多活動的數據庫表太重要了,因此我們一次將刪除限制爲10,000行,並繼續重新發出查詢,直到所有必需的行都被修剪。

我看到下面的選項,並願意見上是最好的,或者其他的選擇建議:

  1. 同時
  2. 使用我們的DELETE指數退避刪除的行數少,但我我擔心這不會有助於我們的具體工作量
  3. 按照MySQL documentation鎖定表。我們可以接受在刪除期間阻止SELECT和UPDATE語句。
  4. 切換到MyISAM表類型。我們使用InnoDB,因爲我們最初是在這張桌子上使用交易。這已不再是這種情況。我不太瞭解具體情況,以瞭解這是否是一種可行的解決方案。
  5. 也許使用UPDATE LOW_PRIORITY。可能是DELETE不會影響SELECT,只有UPDATE,這可能就足夠了。
+1

我遇到的所有死鎖都是由於未提交的事務。確保您正確地運行事務(或者使用自動提交或自動提交關閉並實際處理提交/回滾)。 – localshred 2009-08-20 15:23:04

+0

絕對是一個好點;大多數情況下都是這種情況,但我們實際上並未在此表上進行交易。我們曾經,但不再做。 – ChrisInEdmonton 2009-08-20 15:32:14

回答

4

在進行DML操作,InnoDB鎖掃描的所有行都不匹配。

考慮這個表格佈局:

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

INSERT 
INTO t_tran 
VALUES 
(1, 1), 
(2, 2), 
(3, 3), 
(4, 4), 
(5, 5), 
(6, 6), 
(7, 7), 
(8, 8); 

START TRANSACTION; 

DELETE 
FROM t_tran 
WHERE data = 2 
     AND id <= 5; 

在這種情況下,選擇MySQLidRANGE訪問路徑,它認爲價格比REFdata

在併發交易,您將能夠刪除或更新行678但不排15,因爲它們被鎖定(儘管只排2受到影響)。

如果您從上述條件中刪除id <= 5,您將能夠刪除行,但行3

不幸的是,您無法控制DML操作中的MySQL訪問路徑。

你可以做的最好的事情是正確地索引你的條件,並希望MySQL會選擇這些索引。

+0

謝謝,我們(我的系統管理員和我)認爲這實際上可能是最好的解決方案。我們還減少了刪除量並增加了指數回退。我們會看看是否照顧到這個問題。 – ChrisInEdmonton 2009-08-20 16:23:58

1

請確保您的事務隔離被標記爲已讀提交且不可重複讀取。讀取提交應該是默認的,但我們看到在我們的服務器中innodb默認是可重複讀取的。

您可以通過運行檢查以下內容:

SHOW VARIABLES LIKE 'tx%'; 

爲了設置這一點,在你的my.cnf文件進入folloiwing行:

tx_isolation=READ-COMMITTED