我做简单的时间表服务。
带工作的一张桌子
CREATE TABLE system_jobs (
id bigserial,
job_time timestamp without time zone,
job_function text,
run_on text,
CONSTRAINT system_jobs_pri PRIMARY KEY (id)
)
多个JAVA守护程序选择
job_time < now()
并执行job_function
的所有行(将其id
作为参数传递)job_function示例
CREATE OR REPLACE FUNCTION public.sjob_test(in_id bigint)
RETURNS text AS
$BODY$DECLARE
utc timestamp without time zone;
BEGIN
utc := timezone('UTC', now());
-- This changes not avail from other transactions
UPDATE system_jobs SET run_on='hello' WHERE id = in_id;
PERFORM pl_delay(60); -- Delay 1 minute
UPDATE system_jobs SET job_time = now() + interval '10 seconds', run_on = '' WHERE id = in_id;
RETURN 'done';
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
延迟60秒之前的内部函数我更新
run_on
字段,并在延迟后将其重置。我希望
run_on
在延迟(60秒)内包含“ hello”,并且可以从其他事务中读取,但事实并非如此。我的任务-防止由不同的JAVA守护进程同时执行相同的
job_function
。我要在执行前检查run_on
。我阅读了许多有关交易级别的文档和博客,但是我不知道如何在实践中使用它。
如何配置函数或表或外部进程以允许其他事务看到此更改?
最佳答案
PostgreSQL不支持脏读。参见PostgreSQL documentation:
PostgreSQL的读取未提交模式的行为类似于读取已提交。这是因为这是将标准隔离级别映射到PostgreSQL的多版本并发控制体系结构的唯一明智的方法。
但是看起来有一个变通办法,称为自动交易,可能对您没有帮助。至少有两种方法可以实现它。查看更多信息here和here。
使用这些自主事务,您可以在函数内提交run_on
的更改,以便其他事务能够读取它。