【问题标题】:Locking a table during mysql transaction在mysql事务期间锁定表
【发布时间】:2018-02-27 13:21:51
【问题描述】:

我正在使用 PHP 运行几个 mysql 查询来更改多个表中的值。

基本上是这样的(简化伪代码)

$amount = (SELECT amount FROM wallet WHERE id = 1);
$amount = somelongcomplicatedtask($amount);
(UPDATE wallet SET amount = $amount WHERE id = 23);

可以有许多脚本并行使用 mysql 数据库(写入/读取),我需要确保以下几点:

  • 如果其中一个查询失败,到目前为止完成的所有工作都将恢复(我可以为此使用 TRANSACTIONS)
  • 当我使用表钱包中的两行(1 和 23)时,它们需要被锁定,因此任何想要读取或写入它们的进程(当前进程除外)都必须等待。 (如果不能只锁定行,锁定整个表也可以)

该表使用 InnoDB 引擎。

问题是,如果我用LOCK TABLES wallet WRITE 锁定表,然后运行START TRANSACTION,这将清除锁定。如果我首先运行START TRANSACTION,然后我用LOCK TABLES 锁定表,那么锁定将提交启动的事务......这两件事只是互相关闭,但我需要它们同时激活.

处理这个问题的最佳方法是什么?

【问题讨论】:

    标签: mysql sql innodb


    【解决方案1】:

    MySQL InnoDB 存储引擎已经支持行级锁定。 在这种情况下,您必须对该特定行采取排他锁,以便其他事务将一直等到并且除非第一个事务释放他的锁。更多信息:InnoDB Locking Explained

    【讨论】:

      【解决方案2】:
      BEGIN;
      SELECT ... FOR UPDATE;
      longcomplicated...
      UPDATE ...
      COMMIT;
      

      InnoDB 的FOR UPDATE 很重要,它会锁定行直到UPDATE(实际上直到COMMIT)。

      但是,如果BEGIN...COMMIT 花费“太长”,您会遇到其他问题。默认超时为 50 秒,这对于任何文明的事务设置来说都太长了。如果太长,我们需要讨论其他锁定技术。

      不要不要使用LOCK TABLES

      【讨论】:

        猜你喜欢
        • 2018-08-15
        • 1970-01-01
        • 2011-05-12
        • 2016-03-22
        • 2012-07-23
        • 2011-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多