首页 > 解决方案 > 使用数据库实现的锁定机制

问题描述

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

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

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

我的想法如下:

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

我现在的状态是这样的:

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子句,因为这是无效的语法。

我也会尝试进行有条件的更新,但我不确定如何向调用程序发回该元素当前已锁定的信号。(因为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'值使其爆炸,表明该特定项目当前已被锁定。

我仍在寻找更好/更清洁的方法来做到这一点。

标签: mysql

解决方案


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


推荐阅读