在PostgreSQL 9.6中,此CTE中下面的FOR UPDATE
子句是否必要?
CREATE OR REPLACE FUNCTION next_job()
RETURNS json
LANGUAGE 'sql'
AS $BODY$
WITH thejob AS (
SELECT jobs.*, company.*
FROM (
select * from jobs
WHERE NOT EXISTS (SELECT * from jobs AS j2 where jobs.platform = j2.platform and jobs.project = j2.project AND start > now() - interval '1 hour')
order by priority, account_priority, job_id
limit 1) jobs
LEFT OUTER JOIN company
ON jobs.company_id = company.id
, enabled
WHERE enabled.status IS TRUE
FOR UPDATE of jobs
)
UPDATE jobs
SET start = now()
FROM thejob
WHERE jobs.job_id = thejob.job_id
RETURNING json_build_object('job_id', jobs.job_id, 'platform', jobs.platform, 'project', jobs.project, 'firstSeen', thejob.first_seen);
$BODY$;
锁定的目的是确保一次只能由一个工人执行一项工作(这似乎按预期工作),但是调用此函数时偶尔会出现死锁,并且想知道我的显式锁定是否为可能引起问题。
WHERE NOT EXISTS
用于确保同一项目不会再次启动,除非它在1小时后超时。
答案 0 :(得分:0)
由于只涉及一行,因此CTE似乎不必要。仅当您要更新几行并以一定顺序锁定它们以避免死锁时,这才有意义。
由于查询将仅锁定单个jobs
行,因此它本身不能死锁任何东西。
同一事务中还有许多其他数据修改语句,这些语句与您显示的语句一起会导致死锁。
请记住,锁将保持到事务结束!