PostgreSQL 触发器函数耗时过长导致 php 超时
PostgreSQL trigger function taking too long leading to php timeout
问题
我有一个 plpgsql
函数 prepare_download_file
从 php
脚本中传入几个用户定义的参数,将这些参数插入到日志中 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的LISTEN
和NOTIFY
.
问题
我有一个 plpgsql
函数 prepare_download_file
从 php
脚本中传入几个用户定义的参数,将这些参数插入到日志中 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的LISTEN
和NOTIFY
.