更新状态的行锁

发布于 2024-10-17 12:31:42 字数 407 浏览 4 评论 0原文

我有一个“要执行的命令”表,其状态为(“要处理”、“处理”、“完成”)。

我有几个实例(亚马逊 ec2),其中有一个守护进程要求“要执行的命令”。

守护进程请求状态为“toprocess”的行,然后进行处理,并在每个循环结束时将状态更改为“done”。

问题是,在开始该循环之前,我需要将所有行“toprocess”更改为状态“processing”,这样其他实例就不会采用相同的行,从而避免冲突。

我读过有关 innodb 行锁的内容,但我不太了解它们...

SELECT * from Commands where status = 'toprocess' 然后我需要获取这些结果的 ID,并将状态更新为 'processing' ,锁定这些行直到它们被更新。

我该怎么做?

谢谢

I have a table of "commands to do" with a status ('toprocess', 'processing', 'done')

I have several instances (amazon ec2) with a daemon asking for "commands to do".

The daemon asks for rows with status 'toprocess', then it processes, and at the end of each loop it changes the status to 'done'.

The thing is that, before starting that loop, I need to change all rows 'toprocess' to status 'processing', so other instances will not take the same rows, avoiding conflict.

I've read about innodb row locks, but I don't understand them very well ...

SELECT * from commands where status = 'toprocess'
then I need to take the ID's of these results, and update status to 'processing' , locking these rows until they are updated.

How can i do it ?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

朕就是辣么酷 2024-10-24 12:31:42

您可以使用事务,并使用 FOR UPDATE 读取数据,这将阻止其他选择,这些选择包括在选定的行上的 FOR UPDATE

begin transaction;
 select * from commands where status = 'toprocess' for update;
 for each row in the result:
  add the data to an array/list for processing later. 
  update commands set status='processing' where id = row.id;

 commit;

process all the data

阅读有关 用于更新 和 InnoDB 隔离级别

You'd use a transaction , and read the data with FOR UPDATE, which will block other selects that include the FOR UPDATE on the rows that gets selected

begin transaction;
 select * from commands where status = 'toprocess' for update;
 for each row in the result:
  add the data to an array/list for processing later. 
  update commands set status='processing' where id = row.id;

 commit;

process all the data

Read a bit about the FOR UPDATE , and InnoDB isolation levels.

方圜几里 2024-10-24 12:31:42

一个可能的(但不是很优雅)的解决方案可能是首先更新记录,然后读取其数据:

每个守护进程将有一个唯一的 ID,并且该表将有一个名为“所有者”的新列用于该 ID。
然后守护进程将运行类似“UPDATE table SET status='processing',owner='theDeamonId' where status='toprocess'...LIMIT 1”的内容,

当更新运行时,该行被锁定,因此没有其他守护进程可以读取它。
更新后,该行由特定守护程序拥有,然后它可以运行 SELECT 以从该行获取所有必要的数据(WHERE status='processing' ANDowner='theDeamonId')。

最后,最后一次 UPDATE 会将行设置为“已处理”,并且可能(也可能不会)删除所有者字段。将其保留在那里还可以启用一些有关守护进程工作的统计数据。

A possible (yet not very elegant) solution may be to first UPDATE the record, then read its data:

Each deamon will have a unique ID, and the table will have a new column named 'owner' for that ID.
Then the deamon will run something like "UPDATE table SET status='processing', owner='theDeamonId' where status='toprocess' ... LIMIT 1"

While the update runs the row is locked, so no other deamon can read it.
After the update this row is Owned by a specific deamon, then it can run a SELECT to fetch all necessary data from that row (WHERE status='processing' AND owner= 'theDeamonId').

Finally, the last UPDATE will set the row to 'processed', and may (or may not) remove the owner field. Keeping it there will also enable some statistics about the deamons' work.

倾城泪 2024-10-24 12:31:42

据我所知,你不能使用 MySQL 来锁定行(使用内置方法)。不过,您有两个选择:

  1. 如果在释放锁之前任何其他进程都不应该读取您的表,那么您可以使用表级锁定如此处所述

  2. 您可以实现您的通过更新正在处理的每一行中的值来创建自己的基本行锁定,然后让所有其他守护程序检查是否设置了此属性(BIT 数据类型就足够了)。

无论如何,InnoDB 都会在行级别锁定以进行读取和更新,但如果您想在任意时间段内锁定行,那么您可能必须使用第二个选项。

As far as I know you can't use MySQL to lock a row (using a built-in method). You have two options though:

  1. If your table should not be read by any other process until the locks are released then you can use table level locking as described here

  2. You can implement your own basic row locking by updating a value in each row you're processing, and then have all your other daemons checking whether this property is set (a BIT data type would suffice).

InnoDB locks at a row level for reading and updating anyway, but if you want to lock the rows for an arbitrary period then you may have to go with the second option.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文