Chr*_*ton 10 mysql deadlock innodb
我们有一个(目前是InnoDB)表,其中包含大约500,000行.这表示要运行的任务队列.它存储在MySQL数据库中.
一个连续的基础,至少每秒一次,但有时更频繁,我们从中选择数据,然后更新一些行.每天一次,我们从表中修剪旧行.
我们开始在桌面上遇到僵局,这使我们的任务处理停滞不前.这些僵局是在夜间修剪过程中造成的.DELETE,SELECT和UPDATE的组合意味着基本上没有任何生产力可能发生.遗憾的是,我没有SHOW ENGINE INNODB STATUS的输出.
我想知道解决这个问题的最佳选择.请注意,我们的代码会检测死锁并重新发出查询.此外,我们很久以前就发现一次删除所有匹配的行对于看到大量活动的数据库表太过费力,所以我们一次将删除限制为10,000行,并继续重新发出查询,直到所有必要的行都被删除为止.修剪.
我看到以下选项,并希望哪些是最好的意见,或其他选项的建议:
执行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;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,MySQL
选择RANGE
访问路径 on id
,它认为比REF
on便宜data
。
在并发交易,您将能够删除或更新行6
,7
,8
但没有行1
到5
,因为它们被锁定(尽管只有一行2
受到影响)。
如果您id <= 5
从上述条件中删除,您将能够删除除 row 之外的任何行3
。
不幸的是,您无法控制操作中的MySQL
访问路径DML
。
您能做的最好的事情是正确索引您的条件,并希望MySQL
能够选择这些索引。