【问题标题】:InnoDB transactions: Lock wait timeoutInnoDB 事务:锁定等待超时
【发布时间】:2013-07-13 18:36:20
【问题描述】:

我的数据库中有一个表(实际上是一些相关的表),可以通过我们的界面从各个点手动操作,也可以连续地从两个来源自动操作。定期更新可能包含大量数据,并可能导致数千次插入/更新。为了提高插入/更新的性能,我在来自这些自动源的更新周围使用了“SET autocommit = 0”。这导致了预期的性能改进,甚至可能超出预期。但是现在的问题是,如果自动源重叠或手动更新经常执行,数据库会锁定并在一段时间后引发错误:

超过锁定等待超时;尝试重启事务

即使在一个启用自动提交且没有事务的单个语句中也可能会抛出此问题,但我想如果它与事务冲突也是合理的。我已经阅读了各种建议,不幸的是没有理想的解决方案。我想我的选择是:

  1. 尝试在表上按顺序更新/插入,以便所有线程上的锁都以相同的顺序请求并且没有死锁。不幸的是,这是不可能的,需要按照收到的顺序应用更新。

  2. 使用 LOCK TABLES 序列化事务。这在理论上是可能的,但是 a) 除了两个自动源之外,这些表是从系统中的许多点更新的,包括触发器、计划,从各种接口手动更新。在所有这些地方识别和维护 LOCK 表将是一场噩梦,而且没有简单的方法知道所有这些都已被识别,并且 b) LOCK TABLES 必须锁定所有涉及的表和更新/插入虽然不经常但有时可能需要由于更新而更新许多表,并且再次需要识别和维护所有可能被更新的表,以便它们包含在 LOCK TABLES 中。

  3. 在每次更新之前使用信号量表,以实现更新的序列化,就像上面的 LOCK TABLES 但实际上不必使用 LOCK TABLES。这是一个改进,但仍然存在上述 LOCK TABLES 的问题 a)。

还有其他建议吗? autocommit = 0(事务)的改进好处是否可以通过其他不涉及锁的方式来实现?是否可以将 innodb 配置为实际上不锁定或更少锁定更新/插入?

最后的选择可能是转移到 MyISAM 表。这真的会通过大量的插入/更新操作来提高性能吗?

谢谢

【问题讨论】:

    标签: mysql innodb


    【解决方案1】:

    您可以在不使用长事务的情况下实现 autocommit = 0 的好处。

    a) 假设您不需要回滚整个事务,您可以在每 X 条语句中提交事务

    b) 您可以在导入之前/之后使用 ALTER TABLE x DISABLE keys / ALTER TABLE x ENABLE keys 而不是使用 autocommit = 0。这就是操作性能提升的原因——非唯一索引直到事务完成才更新,然后批量更新。

    【讨论】:

    • 感谢您的建议,但不幸的是 a) 并不能解决问题,除非它不太可能发生 b) ALTER TABLE DISABLE KEYS 不适用于 InnoDB。可能会给我们带来一些性能提升的是禁用外键和唯一键,批量插入/更新是受控情况,其中完整性检查通常不会失败,并且可以容忍偶尔的完整性违规
    猜你喜欢
    • 2011-01-24
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多