Deadlocks on MySQL deleting rows

末鹿安然 提交于 2019-12-05 02:41:24

When performing DML operations, InnoDB locks all rows scanned, not matched.

Consider this table layout:

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;

In this case, MySQL selects RANGE access path on id, which it considers cheaper than REF on data.

In a concurrent transaction, you will be able to delete or update rows 6, 7, 8 but not rows 1 to 5 since they are locked (despite the fact that only row 2 was affected).

If you remove id <= 5 from the condition above, you will be able to delete any row but row 3.

Unfortunately, you cannot control MySQL access paths in DML operations.

Best you can do is to index your conditions properly and hope that MySQL will pick these indexes.

Make sure that your transaction isolation is marked as read committed and not repeatable read. Read commited should be the default, but we saw that in our server the innodb default was repeatable read.

You can check by running the following:

SHOW VARIABLES LIKE 'tx%';

In order to set this, in your my.cnf file enter the folloiwing line:

tx_isolation=READ-COMMITTED
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!