【问题标题】:Locking mechanism implemented using the database使用数据库实现的锁定机制
【发布时间】:2018-10-05 17:21:34
【问题描述】:

我正在尝试使用以下 MySQL 表实现锁定机制:

CREATE TABLE Locker (
  `Id` int(11), 
  `locked_until` timestamp null,
  unique index `unique` (`Id` asc)
);

这个想法是会有多个进程接收ids 来处理。处理本身发生在 MySQL 之外,但我想使用数据库表来跟踪当前正在进行的处理,并禁止同时处理相同的 id

我的想法如下:

  • 给定id,我将在表中插入(或更新)相应记录,将locked_until 设置为合理值(通常为`CURRENT TIMESTAMP + INTERVAL 30 SECOND)
  • 在 MySQL 之外进行处理
  • 处理项目时,UPDATE Locker SET locked_until=null WHERE id={current_id}

列表中的第一个项目符号有问题,因为要处理三种不同的情况:

  • id 的行不存在 ==> 应该插入
  • 一行已存在,但未锁定(locked_untilnull 或过去的值)==> 应更新为新的 locked_until
  • 一行已经存在,但它已被锁定 ==> 不应在 DB 中执行任何操作,而是向程序发出不应进行处理的信号。

我现在的状态是这样的:

insert into Locker (Id, locked_until)
values (3, current_timestamp + interval 60 second)
on duplicate key update locked_until = current_timestamp + interval 60 second;

但问题在于它忽略了当前更新的行。我不能添加 WHERE 子句,因为那是无效的语法。

我也会尝试执行conditional update,但我不确定如何向调用程序发回该元素当前已锁定的信号。 (因为 output 在 SQL Server 中不受支持)

是否可以在一条语句中完成所有这些操作?


更新:

我找到了一种方法,但感觉有点 hack-ish:

insert into Locker (Id, locked_until)
values (3, current_timestamp + interval 60 second)
on duplicate key update locked_until = if(locked_until < current_timestamp,
                                                current_timestamp + interval 60 second,
                                                'error');

如果需要评估 if 的第二部分,'error' 值会使其爆炸,表明该特定项目当前已被锁定。

不过,我仍在寻找更好/更清洁的方法。

【问题讨论】:

  • 您可以在current status 查询之后检查受影响的行数。对于新的 Id,它将为 1,而对于更新的现有记录,它将返回 2。如果 Id 存在并且locked_until 未更改,则受影响的行数 = 0。至少这是我在旧的 mariadb 实例上看到的。
  • @YuriLachin 问题在于,如果有锁定记录,无论如何都会进行更新。这只是取决于if 的不同值。不幸的是,在DUPLICATE KEY 之后我不能UPDATE ... WHERE
  • 如果您SET locked_until = if(locked_until current_timestamp, current_timestamp + interval 60 second,locked_until),您是否会受到影响的行数> 0?
  • @YuriLachin 你是对的!您的解决方案就像一个魅力!您可以将其发布为答案,我会接受。谢谢!
  • @Vatev 你是对的; Yuri 的解决方案效果很好。我犯了一个错误。

标签: mysql


【解决方案1】:

您可以在当前状态查询后检查受影响的行数。对于新的 Id,它将为 1,而对于更新的现有记录,它将返回 2。如果 Id 存在并且locked_until 未更改,则受影响的行数 = 0。至少这是我在旧的 mariadb 实例上看到的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 2013-12-07
    • 2015-03-27
    • 1970-01-01
    相关资源
    最近更新 更多