2017-05-05 79 views
0

我做简单的日程安排服务。PostgreSQL:如何在首次交易未完成时使其他交易可读取更新

一个有工作表

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 60之前(通过他们的id作为参数)

工作职务样品

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; 

内部功能秒延迟我更新run_on字段,并在延迟后重置。

我希望run_on包含'你好',而延迟(60秒),并可用于从其他交易中读取,但事实并非如此。

我的任务 - 防止同时执行不同的JAVA守护进程相同的job_function。我想在执行前检查run_on

我读了很多关于交易级别的文档和博客,但我不明白我怎么能在实践中使用它。

如何配置我的函数或表或外部进程以允许其他事务看到此更改?

+0

不可能。 Postgres永远不会允许脏读(未提交的更改) –

回答

1

PostgreSQL不支持脏读。请参阅PostgreSQL documentation

PostgreSQL的Read Uncommitted模式的行为与Read Committed类似。这是因为它是将标准隔离级别映射到PostgreSQL的多版本并发控制体系结构的唯一明智方式。

但看起来像有一种解决方法称为自主事务,可能会帮助你。至少有两种方法来实现它。查看更多信息herehere

使用这些自治事务,您可以在您的函数内提交更改run_on,以便其他事务将能够读取它。

0

只有一种方法可以做到 - 通过dblink。例如:

PERFORM dblink('your server config', 'UPDATE ...');