0

我有 5 个以上的进程同时从同一个 mysql 表中选择行。每个进程选择 100 行,处理它并删除选定的行。

但是我选择并处理了 2 次或更多次相同的行。

如何避免它发生在 MYSQL 端或 Ruby on Rails 端?

该应用程序基于 Ruby On Rails 构建...

4

3 回答 3

4

您的表格似乎是一个工作流程,这意味着您应该有一个指示行状态的字段(在您的情况下为“已声明”)。其他进程应该选择无人认领的行,这将防止进程踩到彼此的行。

如果你想更进一步,你可以使用进程标识符,这样你就知道什么在做什么,也许工作时间太长,以及它是否完成等等。

是的,回到你的旧问题并批准一些答案。我至少看到了一个你肯定错过的。

于 2011-11-04T19:02:20.343 回答
3

埃里克的回答很好,但我想我应该详细说明一下......

你的表中有一些额外的列说:

lockhost VARCHAR(60),
lockpid INT,
locktime INT, -- Or your favourite timestamp.

将它们全部默认为 NULL。

然后你让工作进程通过执行以下操作“声明”这些行:

UPDATE tbl SET lockhost='myhostname', lockpid=12345,
 locktime=UNIX_TIMESTAMP() WHERE lockhost IS NULL ORDER BY id
 LIMIT 100

然后使用 SELECT ... WHERE lockhost='myhostname' 和 lockpid=12345 处理声明的行

处理完一行后,进行必要的更新,并将 lockhost、lockpid 和 locktime 设置回 NULL(或删除它)。

这会阻止同一行同时被多个进程处理。您需要主机名,因为您可能有多个主机在进行处理。

如果一个进程在处理批处理时崩溃,您可以检查“锁定时间”列是否很旧(比处理可能需要的时间早得多,比如几个小时)。然后,您可以只回收一些具有旧“锁定时间”的行,即使它们的锁定主机不为空。

这是数据库中非常常见的“队列模式”;它不是非常有效。如果您有非常高的项目进入/离开队列,请考虑使用适当的队列服务器。

于 2011-11-05T07:32:10.003 回答
0

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

应该为你做

于 2011-11-04T17:01:08.850 回答