有没有办法在 psycopg2 中为数据库事务或数据库查询设置超时?
示例用例:
Heroku 将 django Web 请求限制为 30 秒,之后 Heroku 终止请求,不允许 django 优雅地回滚任何尚未返回的事务。这可能会使未完成的交易在 postgres 上保持打开状态。您可以在数据库中配置超时,但这也会限制与 Web 无关的查询,例如维护脚本分析等。在这种情况下,最好通过中间件(或通过 django)设置超时。
您可以使用选项参数设置连接时的超时。语法有点奇怪:
>>> import psycopg2
>>> cnn = psycopg2.connect("dbname=test options='-c statement_timeout=1000'")
>>> cur = cnn.cursor()
>>> cur.execute("select pg_sleep(2000)")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
psycopg2.extensions.QueryCanceledError: canceling statement due to statement timeout
也可以使用 env 变量进行设置:
>>> import os
>>> os.environ['PGOPTIONS'] = '-c statement_timeout=1000'
>>> import psycopg2
>>> cnn = psycopg2.connect("dbname=test")
>>> cur = cnn.cursor()
>>> cur.execute("select pg_sleep(2000)")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
psycopg2.extensions.QueryCanceledError: canceling statement due to statement timeout
您可以随时使用 SQL 设置每条语句的超时。例如:
SET statement_timeout = '2s'
将中止任何超过 2 秒的语句(紧随其后)(您可以使用任何有效单位作为"s"或"ms")。请注意,当语句超时时,psycopg 会引发异常,您需要注意捕获它并采取适当的措施。
看起来PostgreSQL 9.6添加了空闲事务超时。看:
- https://www.postgresql.org/docs/9.6/static/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT 供参考。
- http://blog.dbi-services.com/a-look-at-postgresql-9-6-killing-idle-transactions-automatically/为例。
PostgreSQL 9.6在Heroku中也受支持,所以你应该能够使用它。