Установить транзакцию\таймаут запроса в psycopg2?

Есть ли способ установить тайм-аут в psycopg2 для транзакций db или для запросов db?

Пример прецедента:
Heroku ограничивает веб-запросы django до 30 секунд, после чего Heroku прекращает запрос, не позволяя django изящно откатываться от любых транзакций, которые еще не вернулись. Это может оставить незавершенные транзакции открытыми в postgres. Вы можете настроить тайм-аут в базе данных, но это также ограничило бы запросы, не связанные с веб-сайтами, такие как аналитика сценариев обслуживания и т.д. В этом случае установка тайм-аута через промежуточное программное обеспечение (или через django) было бы предпочтительнее.

Ответ 1

Вы можете установить таймаут во время соединения с помощью параметра options. Синтаксис немного странный:

>>> 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

Ответ 2

Вы можете установить тайм-аут для каждого оператора в любое время с помощью SQL. Например:

SET statement_timeout = '2s'

отменяет любое утверждение (после него), которое занимает более 2 секунд (вы можете использовать любой допустимый блок как 's' или 'ms'). Обратите внимание, что когда тайм-ауты выписки, psycopg вызывает исключение, и ваша забота - поймать его и действовать соответствующим образом.

Ответ 3

Похоже, PostgreSQL 9.6 добавил тайм-ауты простоя транзакции. См:

PostgreSQL 9.6 также поддерживается в Heroku, поэтому вы сможете использовать его.