Postgres закрывает соединение во время запроса через несколько сотен секунд при использовании Psycopg2 - PullRequest
12 голосов
/ 24 мая 2019

Я использую PostgreSQL 9.6 (в Docker, использую образ postgres: 9.6.13) и psycopg2 2.8.2.

Мой сервер PostgreSQL (локальный) содержит две базы данных.Моя цель состоит в том, чтобы создать материализованные представления в одной из баз данных, которые используют данные из другой базы данных, используя внешние обертки данных Postgres.Я делаю все это из скрипта Python, который использует psycopg2.

Это работает хорошо, пока создание материализованного представления не занимает много времени (т. Е. Если объем импортируемых данных не слишком велик).Однако, если процесс занимает больше, чем ~ 250 секунд, psycopg2 выдает исключение

psycopg2.OperationalError: server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.

. В журналах Postgres не может быть найдено сообщение об ошибке (или какое-либо сообщение об этом).

Создание материализованного представления завершается успешно, если я делаю это из клиента SQL (Postico).

Этот код примерно иллюстрирует то, что я делаю в скрипте Python:

db = pg.connect(
    dbname=config.db_name,
    user=config.db_user,
    password=config.db_password,
    host=config.db_host,
    port=config.db_port
)
with db.cursor() as c:
    c.execute("""
        CREATE EXTENSION IF NOT EXISTS postgres_fdw;
        CREATE SERVER fdw FOREIGN DATA WRAPPER postgres_fdw OPTIONS (...);
        CREATE USER MAPPING FOR CURRENT_USER SERVER fdw OPTIONS (...);
        CREATE SCHEMA foreign;
        IMPORT FOREIGN SCHEMA foreign_schema FROM SERVER fdw INTO foreign;
    """)
    c.execute("""
        CREATE MATERIALIZED VIEW IF NOT EXISTS my_view AS (
            SELECT (...)
            FROM foreign.foreign_table
        );
    """)

Ответы [ 2 ]

2 голосов
/ 27 мая 2019

Добавление параметров keepalive в вызов psycopg2.connect, похоже, решило проблему:

self.db = pg.connect(
            dbname=config.db_name,
            user=config.db_user,
            password=config.db_password,
            host=config.db_host,
            port=config.db_port,
            keepalives=1,
            keepalives_idle=30,
            keepalives_interval=10,
            keepalives_count=5
        )

Я до сих пор не знаю, почему это необходимо.Я не могу найти никого, кто бы описывал необходимость использования ключевых слов параметра keepalives при использовании Postgres в Docker просто для того, чтобы можно было выполнять запросы, которые занимают более 4-5 минут, но, возможно, достаточно очевидно, что никто этого не заметил

0 голосов
/ 27 мая 2019

Возможно, PostgreSQL 9.6 уничтожит ваши соединения после нового тайм-аута, указанного в https://stackoverflow.com/a/45627782/1587329. В этом случае вы можете установить

statement_timeout в postgresql.conf

но это не рекомендуется .

Это может работать в Postico, потому что там было установлено значение.

Чтобы зарегистрировать ошибку, вам нужно установить log_min_error_statement в ERROR или ниже, чтобы она отображалась.

...