【问题标题】:Lock wait timeout exceeded on INSERTINSERT 超过锁定等待超时
【发布时间】:2022-01-19 04:44:26
【问题描述】:

我在 MySQL 5.7(在 AWS RDS Aurora 上运行)上有一个表 Contact,如下所示:

CREATE TABLE Contact (
    id BIGINT NOT NULL AUTO_INCREMENT,
    email VARCHAR(255) NOT NULL UNIQUE,
    firstname VARCHAR(255) NOT NULL,
    lastname VARCHAR(255) NOT NULL,
    createdAt DATETIME,
    updatedAt DATETIME
);

该表有 4 个其他表通过 Contact.id 连接到它,但该关系未使用外键强制执行。 生产表包含超过 10M 行。我最近编写了一个 NodeJS 脚本,它获取联系人 ID 列表并在 Contact 表上运行 DELETE 查询。重要的部分如下所示:

await this.query("DELETE FROM AssociatedTableA WHERE contactId=?", contactId);
await this.query("DELETE FROM AssociatedTableB WHERE contactId=?", contactId);
await this.query("DELETE FROM AssociatedTableC WHERE contactId=?", contactId);
await this.query("DELETE FROM AssociatedTableD WHERE contactId=?", contactId);
await this.query("DELETE FROM Contact WHERE contactId=?", contactId);

上述部分针对从包含 250 万行的一系列 CSV 文件解析的每个联系人 ID 运行。多个工作进程解析 CSV 文件并执行 sn-p。 它不是事务的一部分,也没有显式锁

当此脚本运行时,应用程序处于生产状态,用户正在注册联系人。但是,在几次删除之后,INSERTS 被阻止并出现以下错误:

ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded - try restarting transaction

即使停止所有工作进程并重新启动数据库,也无法添加新联系人。我不得不将应用程序置于维护模式并终止与 MySQL 的所有剩余连接。

所以我的问题是,什么类型的锁可能会阻止插入查询? MySQL InnoDB 不应该永远不会锁定整个表吗?

【问题讨论】:

  • 你需要提交交易吗?
  • @akaphenom 我没有交易。这就是奇怪的部分

标签: mysql node.js amazon-aurora


【解决方案1】:

首先,Aurora 不是 MySQL。它有很多共同的代码,但他们重写了很多,特别是在存储引擎中,这是实现行级锁定的地方。 Aurora 不是开源的,我们无法在托管的 Amazon 环境中运行它,因此很难测试或调试。那么谁知道他们改变了 InnoDB 的哪些锁定行为呢?

对于 InnoDB,INSERT 可以被间隙锁、next-key 锁、自动增量锁或元数据锁阻塞。根据我的经验,如果有一个未完成的锁阻塞它们,前两者最有可能给出 ER_LOCK_WAIT_TIMEOUT 错误。

https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html#innodb-gap-locks

【讨论】:

    猜你喜欢
    • 2016-12-16
    • 2011-01-07
    • 2019-11-20
    • 2017-02-01
    • 2011-12-25
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多