【问题标题】:How do I handle errors so a locked table will unlock in a procedure?如何处理错误,以便锁定的表将在过程中解锁?
【发布时间】:2013-09-17 20:15:41
【问题描述】:

我想要一个执行以下操作的存储过程:

  1. 锁定表

  2. 检查其中的值

  3. 根据该值更新同一张表

  4. 解锁表

如果1到4之间出现错误,表会被解锁吗?还是我需要以某种方式捕获错误? (怎么做?)

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: mysql sql stored-procedures


    【解决方案1】:

    您不能在 MySQL 的存储过程中锁定表。

    存储例程中不允许使用 SQL 语句

    存储的例程不能包含任意 SQL 语句。不允许使用以下语句:

    锁定语句LOCK TABLES 和UNLOCK TABLES。

    ——http://dev.mysql.com/doc/refman/5.6/en/stored-program-restrictions.html

    如果您使用的是 InnoDB,那么您可以通过使用 locking reads 和 SELECT ... FOR UPDATE 锁定感兴趣的行来实现您的目的。当您遇到错误并回滚事务时,行会自动解锁。

    我在this recent answer 中对此进行了详细介绍,其中的问题涉及避免插入冲突,但无论您是否知道您想要的行已经存在,或者它可能存在或不存在,基本概念都是相同的。

    【讨论】:

      【解决方案2】:

      您是否考虑过使用带有 try-catch 块的事务?看到这个:

      BEGIN TRAN
      SAVE TRAN S1 -- Savepoint so any rollbacks will only affect this transaction
      
      BEGIN TRY
          /* Do your work in here */
      END TRY
      BEGIN CATCH
          ROLLBACK TRAN S1 -- rollback just this transaction
          SET @ErrorMessage = ERROR_MESSAGE()
          SET @Severity = ERROR_SEVERITY()
          SET @State = ERROR_STATE()
          RAISERROR(@ErrorMessage, @Severity, @State) -- re-throw error if needed
      END CATCH
      

      【讨论】:

      • 我刚刚看到这是针对 MySQL 的,对吧?我不确定 MySQL;这是针对 T-SQL 的。
      • 这只是 MySQL,但那里有事务。但是事务不会锁定表以防止其他写入,对吗?我认为我需要锁定桌子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 1970-01-01
      相关资源
      最近更新 更多