我正在使用 PL/pgSQL 函数“interpolate_values”进行一些耗时的计算。名为“interpolation_jobs”的表包含有关每个函数调用的监视信息,这样具有给定 job_id 的函数调用的进度应该可以被观察到
SELECT status FROM interpolation_jobs WHERE id = job_id;
“status”列包含值“queued”、“running”或“done”之一。在函数开始时,状态从'queued'变为'running',最后设置为'done':
CREATE OR REPLACE FUNCTION interpolate_values (job_id INTEGER)
RETURNS VOID
LANGUAGE plpgsql VOLATILE
AS $$
DECLARE
BEGIN
EXECUTE 'UPDATE interpolation_jobs
SET status = ''running'', progress = 0.0
WHERE id = ' || job_id || ';';
--
-- ... some extensive database computations ...
--
EXECUTE 'UPDATE interpolation_jobs
SET status = ''done''
WHERE id = ' || job_id || ';';
END;
$$;
我的问题是在函数调用期间状态没有更新。更新实际上发生在函数调用返回时。因此,状态直接从“排队”变为“完成”。线条
EXECUTE 'UPDATE interpolation_jobs
SET status = ''running'', progress = 0.0
WHERE id = ' || job_id || ';';
没有效果。
是否有可能在 PL/pgSQL 中立即更新值,以便在函数调用返回之前可以访问新值?
谢谢!
编辑:
感谢您的所有回答,这对我理解异步数据库操作的一般问题有很大帮助。 dblink 方法对我有用。如果使用相同的数据库,则无需指定 IP/端口/用户:
SELECT * FROM current_database() INTO _db_name;
PERFORM dblink_connect('dbname=' || _db_name);
PERFORM dblink_exec('UPDATE interpolation_jobs SET status = ''running'' WHERE id =' || _job_id);
--
-- ... some extensive database computations ...
--
PERFORM dblink_exec('UPDATE interpolation_jobs SET status = ''done'' WHERE id =' || _job_id);
PERFORM dblink_disconnect();
最佳答案
您似乎想要的是脏读或脏写。这些在 PostgreSQL 中不可用,也不太可能得到支持。
近亲是一种自主交易。同样,PostgreSQL 不支持这些,尽管添加它们的工作正在进行中。
您会发现,即使使用自治事务,也很难编写您自己的高效排队系统。不要走这条路,使用某人已经写过的。排队系统很难写好,尤其是针对 RDBMS。现有系统,如 ZeroMQ、RabbitMQ、PGQ等可能很值得作为替代品进行评估。
最近有人讨论要向 SELECT ... FOR UPDATE
添加一项功能,让 PostgreSQL 跳过锁定的行并获取未锁定的第一行。这个功能目前还没有,绝对最早要到 9.4 才会有,所以不要屏住呼吸。
关于postgresql - 立即更新 PL/pgSQL 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16275076/