6

我正在填充一个 PostgreSQL 表,其中包含之前从另一个数据库中选择的 ~11.000.000 行。我正在使用 Python 和 psycopg2。整个过程估计需要 1.5 小时才能完成。但是,大约 30 分钟后,我得到“连接意外关闭”异常。源代码如下所示:

incursor = indb.cursor()
incursor.execute("SELECT ...")
indb.commit() # (1) close transaction
outcursor = outdb.cursor()
rows = 0
for (col1, col2, col3) in incursor: # incursor contains ~11.000.000 rows
    outcursor.execute("INSERT ...", (col1, col2, col3)) # This fails after ~30 minutes
    row += 1
    if row % 100 == 0: # (2) Write data every 100 rows
         outcursor.close()
         outdb.commit()
         outcursor = outdb.cursor()
incursor.close()
outcursor.close()
outdb.commit()

我插入(1)(2)在第一次尝试失败后,假设打开的事务的时间上限约为 30 分钟,或者游标具有挂起插入的上限。似乎这些假设都不是真的,错误在于其他地方。

这两个数据库都存储在我通过主机端口转发连接的 VirtualBox 机器上。我在主机上运行程序。

这两个数据库都只是用于测试目的,它们没有其他连接需要管理。也许我必须重写这个问题来解决这个问题,但是我需要在其他地方进行非常耗时的插入(大约运行几天),所以我非常担心psycopg2PostgreSQL 中的一些隐藏的时间限制。

4

3 回答 3

5

我不知道 postgresql 本身有任何这样的“隐藏”超时。PostgreSQL 确实有statement_timeout,但如果你点击它,你应该ERROR: canceling statement due to statement timeout在服务器日志中得到一个(它也会记录取消的语句)。我不能为 psycopg2 说话。一定要检查服务器日志是否有任何看起来相关的内容。

可能是网络问题?长时间运行的语句将是一个长时间处于空闲状态的 TCP 连接。也许您的端口转发会清除空闲超过 30 分钟的连接?也许您的 TCP 连接没有使用 keepalive。Postgresql 有一些用于调整 TCP keepalive 的设置(tcp_keepalives_interval 等),您可能还需要进行一些内核/网络配置以确保它们实际启用。

例如,我刚刚尝试在这里连接到我自己的机器,tcp_keepalives_interval默认为 7200,即 2 小时。如果您的端口转发在 30 分钟后中断,则此默认设置不会执行。您可以覆盖客户端连接字符串中使用的设置(假设您可以直接旋转 conninfo 字符串),或者在用户/数据库属性或 postgresql.conf 中设置 GUC 变量。

看:

于 2011-02-23T11:11:24.733 回答
0

要插入数百万行,我会查看填充数据库的官方指南并考虑使用copy

于 2011-02-23T11:14:01.303 回答
0

我有一个更新成千上万行的 django 管理命令。一段时间后,我看到了同样的错误。我相信内存使用量超过了限制。不过,不知道如何在命令中手动控制事务。

于 2011-07-30T17:38:42.897 回答