我有一个带有状态('toprocess','processing','done')的"commands to do“表
我有几个实例(亚马逊ec2),其中有一个守护进程请求"commands to do“。
守护进程请求状态为“toprocess”的行,然后进行处理,并在每个循环结束时将状态更改为“完成”。
问题是,在开始该循环之前,我需要将所有行“toprocess”更改为“processing”状态,这样其他实例就不会使用相同的行,从而避免冲突。
我读过关于innodb行锁的文章,但我不太了解它们……
SELECT * from commands where status = 'toprocess‘然后我需要获取这些结果的ID,并将status更新为'processing’,锁定这些行直到它们被更新。
我该怎么做呢?
谢谢
发布于 2011-02-13 07:36:49
您可以使用事务,并使用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阅读一些关于FOR UPDATE和InnoDB isolation levels的内容。
发布于 2011-02-13 07:28:02
一种可能的(但不是很优雅的)解决方案可能是首先更新记录,然后读取其数据:
每个守护进程都将有一个唯一的ID,并且表将有一个名为'owner‘的新列作为该ID。然后守护进程将运行类似"UPDATE table SET status='processing',owner='theDeamonId’where status='toprocess‘... LIMIT 1“
当更新运行时,行被锁定,因此没有其他守护进程可以读取它。在更新之后,此行由特定的守护进程所有,然后它可以运行SELECT从该行获取所有必要的数据(WHERE status='processing‘,owner= 'theDeamonId')。
最后,最后一次更新会将行设置为“已处理”,并且可能(也可能不)删除owner字段。保存在那里还将启用有关守护进程工作的一些统计信息。
发布于 2011-02-12 01:11:55
据我所知,您不能使用MySQL锁定行(使用内置方法)。不过,您有两个选择:
InnoDB在行级锁定读取和更新,但是如果您想锁定任意时间段的行,那么您可能必须使用第二种选择。
https://stackoverflow.com/questions/4971860
复制相似问题