我一直有一個特定的更新查詢,這似乎應該是非常沒有問題的各種麻煩。我已經改變了名稱,但該表是:Innodb更新鎖定
CREATE TABLE `problem_table` (
`id` int(11) NOT NULL,
`type` enum('TYPE1','TYPE2','TYPE3') NOT NULL,
`date` datetime NOT NULL,
`reference_id` int(11) DEFAULT NULL,
`value` varchar(255) NOT NULL,
`source` varchar(16) DEFAULT NULL,
`problem_field` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `type_idx` (`type`),
KEY `value_idx` (`value`(12)),
KEY `latest_id` (`reference_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
和查詢造成的問題是:
UPDATE problem_table SET problem_field = 20000101 WHERE id = 6526153;
值的problem_field
和id
這裏就不似乎是很重要的。
這個單一的更新是在problem_table
上的各種選擇查詢反覆死鎖,所以我的問題是 - 這個簡單的更新查詢取出了什麼鎖?我應該補充說,這兩個死鎖事務只包含單個查詢。
我已閱讀the docs但他們似乎並不特別全面。
供參考,在這裏是它和它的INNODB狀態報告死鎖的查詢,雖然這僅僅是一個例子了許多不同的查詢:
INSERT INTO temp
SELECT
p.*,
DATE(p.date)
FROM
problem_table p
WHERE p.type IN ('TYPE1', 'TYPE2')
AND p.source = 'FOO';
------------------------
LATEST DETECTED DEADLOCK
------------------------
161107 0:00:00
*** (1) TRANSACTION:
TRANSACTION 3C7788A94, ACTIVE 69 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 10 lock struct(s), heap size 1248, 7 row lock(s), undo log entries 6
MySQL thread id 6558222, OS thread handle 0x7f44a606d700, query id 3110073624 164.55.80.105 sym_dbuser Updating
-- user=XXX progname=XXX host=XXX pid=XXX ldsn=XXX
-- DBI::db=HASH(0x1d15ecb0)
UPDATE problem_table SET problem_field = 'XXXX-XX-XX XX:XX:XX'WHERE id = 'XXXXX'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 1069083 page no 313 n bits 280 index `PRIMARY` of table `XXX`.`problem_table` trx id 3C7788A94 lock_mode X locks rec but not gap waiting
*** (2) TRANSACTION:
TRANSACTION 3C766F450, ACTIVE 831 sec fetching rows, thread declared inside InnoDB 39
mysql tables in use 2, locked 2
47612 lock struct(s), heap size 5339576, 9395927 row lock(s), undo log entries 9194153
MySQL thread id 6558799, OS thread handle 0x7f4203cb6700, query id 3108758081 172.29.1.16 XXX Sending data
-- user=XXX progname=XXX host=XXX pid=XXX [email protected]
INSERT INTO temp
SELECT
p.*,
DATE(p.date)
FROM
problem_table p
WHERE p.type IN ('TYPE1', 'TYPE2')
AND p.source = 'FOO';
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 1069083 page no 313 n bits 280 index `PRIMARY` of table `XXX`.`problem_table` trx id 3C766F450 lock mode S
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 1069083 page no 82008 n bits 280 index `PRIMARY` of table `XXX`.`problem_table` trx id 3C766F450 lock mode S waiting
*** WE ROLL BACK TRANSACTION (2)
編輯:
對於任何人的利益讀下來,我發現INNODB能夠檢測3個或更多事務的死鎖,但它只列出受害者和希望受害者鎖定在死鎖報告中的事務 - 其餘事務不是在那裏列出。
看到這一點,運行三個交易,如:
T(ransaction)1 take S lock on R(ecord) 1
T2 take S lock on R2
T2 take X lock on R1 (hangs waiting for T1)
T3 take S lock on R3
T3 take X lock on R2 (hangs waiting for T2)
T1 take X lock on R3 (deadlock detected)
nope,它是無觸發的 – rbennett485
它看起來像INSERT INTO臨時SELECT ... - 查詢鎖定problem_table。所以如果這個INSERT INTO查詢發生,你的更新查詢就會等待。根據行數量(超過9百萬個被鎖定),這可能會導致更新查詢失敗,因爲在有用的時間內無法獲得日誌。你有一個緩慢的查詢日誌,你能看到,這些插入查詢需要多長時間以及它們執行的頻率? – Seb
@Seb我確實有一個緩慢的查詢日誌,但這些更新沒有出現在它中 - 它們只是出現死鎖,在這種情況下,其他事務總是受害者 – rbennett485