【问题标题】:Database row lock during multiple transactions多个事务期间的数据库行锁定
【发布时间】:2014-01-01 20:01:56
【问题描述】:

你好,新年快乐 :)

我正在使用 Postgresql,我需要一种方法来使工作进程能够锁定特定行,而该进程在该行上运行。它本质上是一个动作表,应该执行一次且只执行一次。每个进程都应该抓取不同的行进行操作。

在这个“操作”期间,工作进程将计算一些值并在一个事务中多次插入数据库(它会在计算和插入数据库之间改变)。

我不知道每个操作需要多长时间(它会有所不同),我需要一种方法来解锁该行,如果该进程死亡/被杀死或系统崩溃(以便其他进程可以抓住该行并完成操作)。

据我所知,Postgresql 的行锁只在一个事务中持续。我正在考虑添加一些标志,这将指示行是否被锁定到表中,但我无法弄清楚如何判断该行是否仍在操作,或者它是否挂起,因为工作进程死了(在后一种情况下,它应该被其他工作进程占用)? (我在该表中有一个完成标志来表示该行已完成/已完成处理)

【问题讨论】:

  • 听起来你想要一些准备好的事务和/或咨询锁的组合。在 postgresql 文档中搜索这两个术语,看看是否有帮助。至于每个进程抓取一行,看看我几天前发布的这个通用方法,看看是否有什么东西跳出来:stackoverflow.com/questions/20846631/…

标签: sql postgresql concurrency transactions locking


【解决方案1】:

您的带有标志的解决方案似乎是可行的,我认为唯一需要做的就是使锁过期。基本上,我构建锁的方式是,我会在获取锁时写一个时间戳并制作它,以便进程必须每隔一段时间(即每 30 秒)更新锁,而它仍然是记录在案。如果进程死亡或无法完成工作,则锁定将过期,并且如果超时时间超过两倍,其他进程可以解锁它。

当进程完成对记录的处理时,它将清除锁定标志并将记录标记为已处理(再次标记另一个标志)。

您可能需要两个字段:一个用于存储时间戳锁定标志,另一个用于指示哪个进程拥有该锁(以防您关心它)。我假设有某种键可用于对表中的记录进行排序,这样“下一步操作”的概念才有意义。

您可以使用这样的查询来获取下一条要处理的记录:

 -- find the next available process and "lock" it by updating it's flag
 UPDATE actions_tabe
    SET LockFlag = @timestamp,
        Process = @processname
  WHERE Id IN (SELECT Id
            FROM actions_table
           WHERE LockFlag IS null
             AND IsComplete = '0'
             AND ScheduledTime < now()
           ORDER BY Scheduledtime ASC, Id ASC
           LIMIT 1);

 -- return the Id and Action of the record that was just marked above
 SELECT Id, Action
   FROM actions_table
  WHERE Process = @processname

这里是小提琴示例:http://sqlfiddle.com/#!11/9c120/26/1

【讨论】:

  • 对于“下一个动作”部分:有一个“何时”列,它指示何时应该执行一个动作(如时间表)。每个进程定期检查数据库(每隔一秒或两秒)并搜索未完成且“何时”时间戳已过去的行。除此之外,它们只是按 id 排序(顺序根本不重要..应该执行每一行)
  • @Davs,Id 和 when 就是您所需要的。 Id 是数字吗?
  • 定期更新时间戳(例如每 30 秒)的想法非常有趣,尽管它可能应该在该进程的单独线程中完成..顺便说一句,我必须为此使用 Perl,我'不确定现在如何实现..
  • 是的,ID 是数字的(Serial 类型 - 在 postgres 中是一个 auto_increment 整数)
  • 同意第二个线程。显然,30 秒是一个任意值。您可能希望根据您的应用程序对其进行定制。至于在 Perl 中产生多个线程 - 我不知道该怎么做。
猜你喜欢
  • 1970-01-01
  • 2018-08-15
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多