postgresql - Postgres statement_timeout 没有按预期工作
问题描述
我正在研究一个用例,在我当前的 api 应用程序中,我需要终止运行超过 30 秒的任何查询(因为我的服务器有 30 秒的超时,但查询继续在 Postgres 上运行)。
因此,经过一番发现,我遇到了 postgres 中的 statement_timeout 配置。并在我的 sqlAlchemy 代码中实现它,如下所示:
@contextmanager
def db_session():
"""Executes the query."""
import os
from my_aws import secretsmanager
secret_name = f'<my_secrey_key>'
secret = secretsmanager.get_secret(secret_name)
conn = f'{secret["dbname"]}://{secret["username"]}:{secret["password"]}@' \
f'{secret["host"]}:{secret["port"]}/{secret["dbname"]}'
eng = create_engine(
conn,
connect_args={'options': '-c statement_timeout=30s'})
connection = eng.connect()
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=True, bind=eng))
yield db_session
db_session.close()
connection.close()
所以我的期望是,任何无法在 30 秒内完成的查询都应该超时并返回错误。
所以在测试这个的时候。
我在我的一个表中放置了一个锁,通过这样做来延迟我的查询:
BEGIN WORK;
LOCK TABLE <schema>.<table_name> IN ACCESS EXCLUSIVE mode;
然后我触发一个查询锁定表的 API 调用(从上面)。此 api 未按预期响应,因为查询无法在 30 秒内执行。
但是查询不会终止,我仍然可以看到它在pg_stat_activity
SELECT pid, age(clock_timestamp(), query_start), usename, query
FROM pg_stat_activity
WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%' and usename='api_user'
ORDER BY query_start desc;
所以上面的查询给出了响应:
pid |age |usename |query
----|---------------|--------|-------------------------------
3334|00:05:17.962059|api_user|SELECT count(*) AS count_1 ¶FRO
1752|00:05:22.577919|api_user|COMMIT
1754|00:05:22.627446|api_user|COMMIT
3270|00:05:22.791417|api_user|SELECT count(*) AS count_1 ¶FRO
1755|00:05:23.058261|api_user|COMMIT
1753|00:05:23.123582|api_user|COMMIT
1689|00:05:24.149163|api_user|SELECT count(*) AS count_1 ¶FRO
1759|00:05:24.579171|api_user|SELECT DISTINCT sum(public.dema
1760|00:05:24.631371|api_user|SELECT count(*) AS count_1 ¶FRO
如您所见,锁定表上的查询仍在等待超过 5 分钟。
我在这里对 statement_timeout 的理解有问题吗。
仅供参考:我可以看到这个查询的结果是在 postgres 上设置了超时:
show statement_timeout;
结果:
statement_timeout|
-----------------|
30s |
解决方案
我建议您将参数设置为postgresql.conf
(那么它对整个 PostgreSQL 服务器有效)或 with ALTER DATABASE
(那么它仅对与该数据库的新连接有效)。
如果这不起作用,则必须在某处覆盖该设置。要进行调试,请使用 SQLAlchemy 运行以下 SQL 语句:
SELECT current_setting('statement_timeout');
但是,当我查看您的查询时,也许一切正常:将state
列添加到pg_stat_activity
查询中并检查是否state
确实是active
. 也许查询已经被取消,并且状态是idle
或idle in transaction (aborted)
(请注意,它query
显示了该连接上的最后一个查询,它不再需要处于活动状态)。
推荐阅读
- visual-studio-code - VSCode 中的 Jupyter 笔记本扩展以折叠单元格
- xamarin - 如何更改条目下划线的颜色?
- matlab - 使用矢量化替换两个 for 循环?
- angular - 路径前的 HttpClient 斜杠
- video - 实时视频流裁剪和重新合成:您对此有何看法?
- webrtc - GCC(谷歌拥塞控制)是否在 WebRTC 中实现?
- python-3.x - Boto3 无法从名称中包含时间戳的文件中读取元数据
- java - Spark:无法为平台加载本机 hadoop 库
- python - 创建嵌套字典,为每个键提供值范围
- amazon-redshift - 为什么我得到一个“列
关系的 在 dbt 中运行模型但在 SQL 客户端中运行时不存在”错误?