【问题标题】:Making an INSERT ... SELECT statement atomic使 INSERT ... SELECT 语句原子化
【发布时间】:2014-02-21 15:59:36
【问题描述】:

我有两个表:一个存储数据,另一个存储锁以指示用户何时对该数据进行操作。我想从第一个表中选择一些项目,使它们匹配多个条件并且在另一个表中没有相应的锁,然后将这些项目的锁添加到第二个表中。由于许多用户可能同时尝试锁定项目,因此必须以原子方式完成此操作。

我已经编写了下面的 SQL 语句来尝试执行此操作,但收到错误 Deadlock found when trying to get lock;

INSERT INTO table2 (id, user, date)
    SELECT id, ?, NOW()
    FROM table1
    LEFT JOIN table2 USING id
    WHERE locked IS NULL AND <several conditions on table1>
    ORDER BY date 'DESC'
    LIMIT 15;

有什么方法可以在不锁定表的情况下使其成为原子操作?目前我正在使用事务并在不成功时重新尝试,但我对这是否可以避免感兴趣。我在 InnoDB 中使用 MySQL 5.0.95 版。

谢谢

编辑

经过进一步思考,我意识到虽然锁定 table1 是不可接受的,但我可以锁定 table2。由于我实际上不能在语句中锁定表(因为如果我选择锁定其中一个表,我必须锁定所有表),我可以改为使用 GET_LOCK 创建互斥锁,以防止多个进程同时调用此代码。我还没有机会测试这种方法,但感觉它可能是一个比事务更轻量级的解决方案。

【问题讨论】:

  • 与您的问题无关,但如果locked是table2中的一个字段,您必须将其上的过滤器从where子句移动到join子句。否则你实际上有一个内部连接。
  • 我绝对需要阅读更多关于连接如何工作的信息,因为我不了解不同类型的连接。我假设如果第一个表中的大多数项目都有相应的锁,你的建议会提高性能吗?由于 table2 通常是空的,它是否提供任何其他好处?

标签: mysql sql innodb


【解决方案1】:

没有。这就是交易的全部内容。他们在一个原子操作中组织了一堆语句,该操作整体上要么成功,要么失败。

Here 你可以找到一些关于 optimisticpesimistic 锁的解释,也许你会觉得有用。 Here 您可以找到有关 InnoDB 中使用的锁定机制(悲观锁定)的一些详细信息。 Here 你可以找到关于如何在 mysql 中实现乐观锁定的指南。

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 1970-01-01
    • 2012-10-18
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2021-10-19
    相关资源
    最近更新 更多