2

我的数据库中有一个表(实际上是一些相关的表),可以通过我们的界面从各个点手动操作,也可以连续地从两个来源自动操作。定期更新可能包含大量数据,并可能导致数千次插入/更新。为了提高插入/更新的性能,我在来自这些自动源的更新周围使用了“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 表。这实际上会通过繁重的插入/更新操作实现性能改进吗?

谢谢

4

1 回答 1

0

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

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

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

于 2013-07-14T16:30:31.833 回答