我有处理表中json数据的php脚本:
id, data, processed_at
我同时运行多个处理未处理行的脚本:
SELECT * FROM data WHERE processed_at IS NULL
我需要确保脚本不会获取和处理另一个脚本已经在处理的相同行。因此,我又添加了两行,我使用以下查询而不是上面的简单查询:
id, data, processed_at, processing_uuid, processing_at
UPDATE data SET
processing_uuid = '<a uuid>',
processing_at = NOW()
WHERE processed_at IS NULL
AND processing_uuid IS NULL;
SELECT * FROM data WHERE processing_uuid = '<a uuid>';
现在我可以处理返回的行,并且不会发生冲突。
不幸的是,我不能在我的某些表中添加这些额外的必需列,我需要一种方法来实现相同的目标。我想到了一个processing_locks
表:
id, processable_table, processable_id, processing_uuid, processing_at
1, data, 1, <a uuid>, '2019-01-01 00:00:00'
不幸的是,我认为我不能使用上述方法,我可以先更新然后选择。
我希望得到一些反馈或提示,说明通常如何处理这种情况,其中多个脚本从同一表中获取和处理行。
假设您的数据表是
create table data (
id bigint not null,
data text,
processed_at timestamp,
primary key (id)
);
您可以按以下方式创建锁表:
create table processing_locks (
processable_table varchar(50) not null,
processable_id bigint not null,
processing_uuid varchar(50),
processing_at timestamp,
primary key (processable_table, processable_id),
index (processing_uuid)
);
现在,您可以插入未处理的行,而不是更新查询
insert ignore into processing_locks (
processable_table,
processable_id,
processing_uuid,
processing_at
)
select 'data', id, '<process_uuid>', now()
from data
where processed_at is null;
由于(processable_table, processable_id)
的组合是唯一的(主键(,因此没有其他进程可以插入相同的行。
使用 UPDATE-JOIN 查询在data
表中设置processed_at
列:
update data d
join processing_locks l
on l.processable_table = 'data'
and l.processable_id = d.id
set d.processed_at = l.processing_at
where l.processing_uuid = '<process_uuid>'
and d.processing_at is null;
获取要处理的所有行:
select d.*
from data d
join processing_locks l
on l.processable_table = 'data'
and l.processable_id = d.id
where l.processing_uuid = '<process_uuid>';
准备好处理数据后,清理锁表:
delete processing_locks
where processing_uuid = '<process_uuid>';