2011-02-23 87 views
5

我正在用另一个数据库之前选择的〜11.000.000行填充PostgreSQL表。我正在使用Python和psycopg2。整个过程估计需要1.5小时才能完成。但是,大约30分钟后,我发现“连接意外关闭”异常。源代码看起来是这样的:执行大插入时,PostgreSQL连接意外关闭

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机器上。我在主机上运行程序。

这两个数据库都只是为了测试目的,他们没有其他的连接来管理。也许我必须重写这个问题才能解决这个问题,但是我需要在其他地方插入非常耗时的内容(大约需要几天的时间),所以我非常关注psycopg2或PostgreSQL中的一些隐藏时间限制。

+1

问题可能出在您的work_mem变量中。 AFAIK这个变量设置允许一个连接的最大内存。检查日志应该有一个关于什么是错误的条目 – Voooza 2011-02-23 10:49:35

+0

但是,然后SELECT语句根本不起作用,不是吗?但是我没有连接到'outdb'。 – WolfgangA 2011-02-23 11:11:47

+0

使用“COPY”或更大的交易。在一次交易中只执行100条记录,会给您提供约110条记录。000个交易来完成整个工作。一个7400rpm的驱动器每秒只能处理120次提交(除非因缓存而存在,否则会导致不可靠)。您目前的问题听起来像是一个网络问题。 – 2011-02-23 11:26:18

回答

4

我不知道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变量。

参见:

+0

非常感谢您的链接! – WolfgangA 2011-02-23 13:26:44

0

要插入的行millons,我会通过官方guide看填充一个DB和考虑使用copy

0

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