代码之家  ›  专栏  ›  技术社区  ›  ChrisInEdmonton

MySQL删除行时出现死锁

  •  10
  • ChrisInEdmonton  · 技术社区  · 17 年前

    我们有一个(目前为InnoDB)表,其中包含大约500000行。这表示要运行的任务队列。它存储在MySQL数据库中。

    在连续的基础上(至少每秒一次,但有时更频繁),我们从中选择数据,然后更新一些行。我们每天修剪一次桌子上的旧行。

    我想知道处理这件事的最佳选择。注意,我们的代码检测死锁并重新发出查询。此外,我们很久以前就发现,一次删除所有匹配的行对一个有大量活动的数据库表来说太麻烦了,因此我们将一次删除的行数限制为10000行,并继续重新发出查询,直到所有必要的行都被删除为止。

    我看到以下选项,并希望就哪一个是最好的提出意见,或对其他选项提出建议:

    1. 一次删除更少的行
    2. 在我们的删除上使用指数退避,尽管我担心这对我们的特定工作负载没有帮助
    3. 根据锁定表 MySQL documentation . 我们可能可以接受在删除期间阻止SELECT和UPDATE语句。
    4. 切换到MyISAM表类型。我们使用InnoDB是因为我们最初在这个表上使用事务。现在已经不是这样了。我对细节不够熟悉,不知道这是否是一个可行的解决方案。
    5. 可能使用更新低优先级。可能是删除不影响选择,只影响更新,这可能就足够了。
    2 回复  |  直到 17 年前
        1
  •  6
  •   Quassnoi    17 年前

    表演时 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;
    

    在这种情况下,, MySQL 挑选 RANGE 上的访问路径 id REF 在…上 data

    在并发事务中,您将能够删除或更新行 6 , 7 , 8 但不是排 1 5 因为它们是锁定的(尽管只有一行 2 受到影响)。

    如果你移除 id <= 5 根据上述条件,您可以删除除行以外的任何行 3 .

    MySQL 中的访问路径 DML 操作。

    你所能做的最好的事情就是为你的情况编制适当的索引,并希望 我们将选择这些索引。

        2
  •  2
  •   David Rabinowitz    17 年前

    您可以通过运行以下命令进行检查:

    SHOW VARIABLES LIKE 'tx%';
    

    要进行设置,请在my.cnf文件中输入以下行:

    tx_isolation=READ-COMMITTED