PostgreSQL 触发器函数耗时过长导致 php 超时

PostgreSQL trigger function taking too long leading to php timeout

问题

我有一个 plpgsql 函数 prepare_download_filephp 脚本中传入几个用户定义的参数,将这些参数插入到日志中 table adc_query_log 然后使用它们构建一个 sql 查询,该查询 select 是一堆数据,将结果复制到 csv 最后 returns 一个唯一的 id 这是php 脚本中需要。 id 是一个关键部分,因为 php 脚本使用它来 select 3 个输出文件,将它们打包到 .zip 存档中,并向用户发送电子邮件下载 link.

根据参数的不同,查询可能会执行得非常快,其他时候我发现它花费的时间超过 45 秒并且就 php 脚本而言超时,所以它不会获取它需要的唯一 ID。

建议的解决方案

prepare_download_file 函数分成两部分,以便第一部分仅将参数插入日志 table 和 returns 唯一 ID,这应该立即发生(第一个列 id 是类型 serial):

INSERT INTO adc_query_log
  VALUES (DEFAULT,query_type,severity,year_range,local_authorities)
RETURNING id INTO session_id;

第二部分 make_download_file() 通过触发函数执行 returns NULL:

CREATE TRIGGER make_download_file AFTER INSERT ON adc_query_log
  FOR EACH ROW EXECUTE PROCEDURE make_download_file();

从 table 中读取插入的值以构建 sql 查询,然后执行所有繁重的工作 - 据说在唯一 ID 返回到 php 脚本之后.

问题

RETURNING id INTO session_id位是否等到触发函数完成后才将此事务标记为完成,然后返回id?如果不行,有什么办法可以强制不等待吗?

服务器是运行PostgreSQL 8.4

我 90% 确定您必须等待触发器结束才能获取 ID,因此超时会再次发生。

所以在这种情况下你应该得到 id(正如你所说的几乎是即时的),然后使用 id

再次调用存储过程

在触发函数完成之前,语句不会return。

我会将需要很长时间的作业放入“队列”table,并有一个单独的进程异步处理队列中的作业。这样你就不用担心超时了。

进程之间的通信,既可以定时拉取状态,也可以使用PostgreSQL的LISTENNOTIFY.