Skip to content

Пул соединений не заменяет соединение, закрытое сервером: после перезапуска PostgreSQL все операции падают с Connection is not open #148

Description

@sfaqer

Версия: entity 5.4.0.0, КоннекторPostgreSQL, OneScript 2.2.0.

После перезапуска PostgreSQL менеджер сущностей больше не работает: соединение, разорванное сервером, остается в пуле и выдается снова, и каждая следующая операция падает с Connection is not open, хотя база уже доступна. Восстанавливается только перезапуском процесса.

Воспроизведение, сущность:

&Идентификатор
&ГенерируемоеЗначение
&Колонка(Тип = "Целое")
Перем Идентификатор Экспорт;

&Колонка
Перем Текст Экспорт;

&Сущность(ИмяТаблицы = "Записи")
Процедура ПриСозданииОбъекта()
КонецПроцедуры

Сценарий: раз в 2 секунды сохраняет запись, на девятой секунде PostgreSQL перезапускается (docker restart):

#Использовать entity

ПодключитьСценарий(ОбъединитьПути(ТекущийКаталог(), "Запись.os"), "Запись");

СтрокаСоединения = "Host=psql;Username=postgres;Password=postgres;Database=postgres;port=5432;";
ИсточникДанных = Новый ИсточникДанных("Основной", Тип("КоннекторPostgreSQL"), СтрокаСоединения, Новый Массив, 10);
МенеджерСущностей = Новый МенеджерСущностей(ИсточникДанных);
МенеджерСущностей.ДобавитьКлассВМодель(Тип("Запись"));
МенеджерСущностей.Инициализировать();

Для Номер = 1 По 20 Цикл
	Попытка
		Запись = Новый Запись();
		Запись.Текст = "попытка " + Номер;
		МенеджерСущностей.Сохранить(Запись);
		Сообщить(СтрШаблон("%1: записано, всего %2", Номер, МенеджерСущностей.Получить(Тип("Запись")).Количество()));
	Исключение
		Сообщить(СтрШаблон("%1: %2", Номер, КраткоеПредставлениеОшибки(ИнформацияОбОшибке())));
	КонецПопытки;
	Приостановить(2000);
КонецЦикла;
1: записано, всего 1
2: записано, всего 2
3: записано, всего 3
4: Внешнее исключение (Npgsql.PostgresException): 57P01: terminating connection due to administrator command
5: Внешнее исключение (System.InvalidOperationException): Connection is not open
6: Внешнее исключение (System.InvalidOperationException): Connection is not open
...
20: Внешнее исключение (System.InvalidOperationException): Connection is not open

База отвечает уже к пятой попытке, но все следующие операции идут через то же закрытое соединение.

Причина, насколько видно по internal/Классы/ПулСоединенийСБД.os: ВзятьСвободное выдает соединение из очереди свободных, не проверяя Открыт() коннектора, а ВернутьВПул закрывает и заменяет только соединение с незавершенной транзакцией (Испорчено()). Соединение, закрытое сервером, возвращается в пул как исправное. Кроме того, соединение закрепляется за потоком исполнения, и долгоживущий поток, например фоновое задание приложения, держит испорченное соединение до своего завершения.

В приложении на autumn-data это выглядит так: после перезапуска базы и фоновые задания, и обработчики HTTP-запросов падают до перезапуска процесса.

Как вариант исправления: при выдаче соединения из пула и при использовании закрепленного соединения проверять Открыт() и заменять закрытое соединение новым, а ошибку соединения (закрытое соединение, 57P01 и подобные) считать порчей соединения, чтобы ВернутьВПул его закрыл.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions