【问题标题】:Preventing lock wait timeouts with INSERT ... SELECT使用 INSERT ... SELECT 防止锁定等待超时
【发布时间】:2019-01-25 22:05:11
【问题描述】:

我的应用程序有一个 InnoDB books 表。每天有几次非常大量的独立INSERTUPDATE 查询针对books 表运行。

应用的传入请求还会使用INSERT INTO [tmp table] (SELECT FROM books ...) 基于books 生成一个临时表。

根据the MySQL docs on INSERT ... SELECT,此语法锁定books,直到填充临时表。

books 表上来自这些选择、插入和更新的锁组合会周期性地压倒 MySQL,从而导致锁等待超时。

我尝试了来自this percona article 的建议,将books 中的SELECT 转储到一个输出文件中,将INSERT 作为单独的步骤执行。这避免了选择锁定,但加载速度过慢。

我是否缺少INSERT ... SELECT 的替代方案,它不会在不牺牲性能的情况下锁定books 表?

【问题讨论】:

  • 请给我们一些SELECT FROM books ...的例子;可能有一些方法可以提高它们的性能,从而消除问题。

标签: mysql mariadb innodb


【解决方案1】:

我是 MySQL 菜鸟,可能理解错误,但是

INSERT INTO [tmp table] (SELECT FROM books ...)

不应对books 表设置任何锁,而应仅对tmp_table 设置任何锁,除非您的事务隔离级别是SERIALIZABLE。

UPDATE 可以在 READ COMMITTED 隔离级别上运行,这样 InnoDB 就不需要在每一行上都持有锁直到事务结束(尽管这仅在 WHERE 部分仅包含索引列时才有效)。

【讨论】:

  • 感谢@Croco,这让我朝着正确的方向前进。似乎SERIALIZABLE REPEATABLE READ 隔离级别在books 表上的INSERT ... SELECT 事务锁定,防止其他进程写入。如果该查询完全不需要隔离,则此级别。在我的简化测试用例中将其设置为 READ COMMITTED 可以解决这两个问题,1) 写入 books 可能发生在其他事务中,而 INSERT ... SELECT 事务尚未提交,2) 如果事务持有 books 上的锁定首先,INSERT ... SELECT 不会被屏蔽。
猜你喜欢
  • 1970-01-01
  • 2016-12-16
  • 2011-01-07
  • 1970-01-01
  • 2019-11-20
  • 2017-02-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多