Соединение с PostgreSQL неожиданно закрывается при выполнении большой вставки - PullRequest
5 голосов
/ 23 февраля 2011

Я заполняю таблицу 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, который я подключаю через переадресацию портов с хоста.Я запускаю программу на хост-машине.

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

Ответы [ 3 ]

4 голосов
/ 23 февраля 2011

Я не знаю ни одного такого "скрытого" тайм-аута в самом 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), или установить переменную GUC в свойствах пользователя / базы данных или postgresql.conf.

См .:

0 голосов
/ 30 июля 2011

У меня есть команды администратора django, которые обновляют тысячи тысяч строк. Через некоторое время я вижу ту же ошибку. Я считаю, что использование памяти превышает лимит. Не знаю, как вручную управлять транзакцией в командах.

0 голосов
/ 23 февраля 2011

Чтобы вставить миллионы строк, я бы посмотрел официальное руководство по заполнению БД и рассмотрел вопрос об использовании copy .

...