我有一個MySQL大致描述如下(實際上MariaDB的52年5月5日)數據庫:如何訂購複合索引以防止插入死鎖?
CREATE TABLE table1 (
id INT NOT NULL AUTOINCREMENT,
col1 INT,
col2 VARCHAR(32),
col3 VARCAHR(128),
PRIMARY KEY (ID),
UNIQUE KEY index1 (col1, col2, col3)
);
有更多的列,但都是在UNIQUE
鍵裏面,有表中沒有其他按鍵。
我運行插入到這個數據庫python腳本的多個線程。每個線程執行100-1000左右使用插入mysql.connector的executemany
這樣
ins_string = "INSERT IGNORE INTO table1 ({0}) VALUES ({1});"
cursor.executemany(ins_string.format(fields, string_symbols), values)
我碰上一致的死鎖問題。我認爲這些問題是由於每個線程根據我的Python列表values
的生成順序以某種半隨機順序鎖定在table1的行之間所致。這有點通過測試驗證;當我使用24個線程從頭開始構建新的數據庫時,每個executemany()
語句的死鎖率大於80%,但到數據庫中有100多行時,死鎖率幾乎爲零。
我認爲僵局是線程AUTOINCREMENT競爭的結果的可能性,但在默認的InnoDB「連續」鎖定模式,它似乎並不像這應該發生。每個線程都應該得到table level lock直到INSERT結束。然而,AUTOINCREMENT和INSERT鎖的交互方式讓我感到困惑,所以如果我有這個錯誤,請讓我知道。
因此,如果問題是由唯一鍵的隨機排序ISH造成的,我需要將它們傳遞到MySql之前訂購的蟒蛇insert語句的一些方法。該索引由MySql以某種方式散列,然後進行排序。我如何可以在python中複製哈希/排序?
我想諮詢一下解決我的問題就在這裏的診斷,但如果你看到我的診斷是錯誤的,再次,請讓我知道。
有8列,所有這些列都在UNIQUE索引中;否則就是完整的'CREATE TABLE'語句。 'id'列存在作爲各種子表的外鍵。我從來沒有運行比CPU核心更多的線程,通常我在48核心服務器上,而限制到24個線程或更少(還有其他進程正在進行)。 – kingledion
@kingledion - 行;這些答案看起來很合理因此,我投票選擇(1)預先排序executemany的行和(2)更小的批次。少於24條的線程可能有助於避免死鎖,但可以減少工作量 - 無法預測它是否值得做。什麼版本的MySQL?舊版本在24個線程中效率低下。 –
這是MariaDB 5.5.52。我想我應該提到它是MariaDB ...什麼構成了「舊」版本? – kingledion