【问题标题】:Postgres closes connection during query after a few hundred seconds when using Psycopg2使用 Psycopg2 时,Postgres 在几百秒后在查询期间关闭连接
【发布时间】:2019-10-10 21:26:05
【问题描述】:

我正在运行 PostgreSQL 9.6(在 Docker 中,使用 postgres:9.6.13 映像)和 psycopg2 2.8.2。

我的 PostgreSQL 服务器(本地)托管两个数据库。我的目标是在一个使用 Postgres 的外部数据包装器的数据库中使用来自另一个数据库的数据的数据库中创建物化视图。我通过一个使用 psycopg2 的 Python 脚本来完成这一切。

只要创建物化视图不会花费太长时间(即,如果导入的数据量不太大),这种方法就可以很好地工作。但是,如果该过程花费的时间超过大约 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
        );
    """)

【问题讨论】:

    标签: python postgresql psycopg2


    【解决方案1】:

    psycopg2.connect调用中添加keepalive参数似乎解决了问题:

    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
            )
    

    我仍然不知道为什么这是必要的。我找不到其他任何人描述过在 Docker 中使用 Postgres 时必须使用 keepalives 参数关键字才能运行需要超过 4-5 分钟的查询,但也许很明显,没有人注意到它?

    【讨论】:

    • 根据postgresql.org/docs/current/libpq-connect.htmlkeepalives的默认值已经是1。所以连接应该保持活动状态。但对于我的连接,它已被OperationalError 关闭。
    • 也可以使用其他参数可以设置为0使用系统默认值。但是我不确定在哪里可以找到默认参数。也许它们是特定于操作系统的。
    • 我在尝试使用 FDW 表创建多个物化视图的设置完全相同的情况下遇到了完全相同的问题。但 5 分钟后,FDW 连接关闭。我尝试了keepalives,但它似乎对我不起作用。我的 postgres 日志显示 psycopg2 正在中止事务,因为与 fwd 服务器的连接丢失。
    【解决方案2】:

    可能是 PostgreSQL 9.6 在 https://stackoverflow.com/a/45627782/1587329 提到的新超时后终止了您的连接。在这种情况下,您可以设置

    postgresql.conf 中的statement_timeout

    但它是not recommended

    它可能在 Postico 中工作,因为该值已在那里设置。

    要记录错误,您需要将 log_min_error_statement 设置为 ERROR 或更低才能显示。

    【讨论】:

    • 嗨,idle_in_transaction_session_timeout 已经设置为 0(所有其他超时也是如此)。 log_min_error_statement 已设置为 ERROR
    • 只是为了确保:statement_timeout 也是 0?这似乎是在 9.6 中引入的
    • 是的,statement_timeout 为零。
    • 您是否尝试设置connect_timeout 中提到的stackoverflow.com/questions/27641740/python-psycopg2-timeout
    • 是的,但我不知道为什么这样做会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多