从 RDS postgres 只读副本和 sqlalchemy 流式传输大型结果集过早终止

Streaming large result sets from an RDS postgres read replica and sqlalchemy terminates prematurely

我正在尝试 运行 在设置为只读副本的 Postgres 9.4 RDS 服务器上使用 SQLAlchemy 和以下代码进行大型查询。

    # self.sa_engine is a SQLAlchemy engine
    with self.sa_engine.connect() as conn:
        conn = conn.execution_options(stream_results=True)

        # pd = pandas
        # self.sql = "select * from mylargetable"
        for chunk in  pd.read_sql(self.sql, conn, chunksize=50000):
            # do stuff, write file, etc....

问题是我在大约 30-60 秒后收到以下错误。在此期间,正在按预期写入文件。

TransactionRollbackError: terminating connection due to conflict with recovery
DETAIL:  User query might have needed to see row versions that must be removed.

我用谷歌搜索的所有内容都说要在 RDS 中的只读副本上设置以下参数:

hot_standby_feedback=1
max_standby_archive_delay=600000
max_standby_streaming_delay=600000

设置了这些参数后,我希望仅当查询 运行 超过 10 分钟时才会出现上述错误,但我会在 30-60 秒后得到它。

此外,我对这个问题的理解是,只有在主数据库中的 table 被修改而副本查询为 运行ning 时才会发生。然而,这个 table 已经几个月没有更新了。

当我 运行 它针对 master 数据库(我不能在生产环境中这样做)和当我 运行 它针对较小的 table 时,所有这些都有效读取副本。

我完全被难住了,希望得到任何帮助。

刚问完这个问题,我就搜索了默认设置为30秒的参数,找到了解决方案。我还需要调整一个参数:

wal_receiver_timeout=600000

设置成功了!

如果出于任何原因您无权更改数据库的配置,and/or 如果这样做没有帮助。完全客户端修复可能是:

使用isolation_level="REPEATABLE_READ"

my_engine = sqlalchemy.create_engine(f"{my_db_url}", isolation_level="REPEATABLE_READ")

线程中也有类似的建议:https://www.postgresql.org/message-id/7F74C5EA-6741-44FC-B6C6-E96F18D761FB@simply.name

这个“修复”当然应该与有关隔离级别的知识一起使用:https://www.postgresql.org/docs/14/transaction-iso.html