PostgreSQL: База данных занята другими пользователями (SQL state 55006)
Управление соединениями в PostgreSQL и суть конфликта
Ошибка «ERROR: database "dbname" is being accessed by other users (SQL state 55006)» (База данных занята другими пользователями) возникает в СУБД PostgreSQL при попытке выполнить DDL-операции, требующие эксклюзивной блокировки всей базы данных (Exclusive Lock). Наиболее частые операции: DROP DATABASE (удаление базы при разворачивании бэкапа) и ALTER DATABASE ... RENAME TO (переименование при копировании продуктивной базы в тестовую). В связке с сервером 1С:Предприятие, процессы rphost постоянно удерживают пул открытых TCP-соединений к PostgreSQL. Пока хотя бы одна транзакция или сессия (даже в статусе idle) держит базу, СУБД отклонит команду удаления. Бизнес-риски: автоматические скрипты CI/CD по обновлению тестовых контуров 1С падают с ошибкой, невозможность освободить диск.
Состояния соединений (pg_stat_activity)
| Статус (state) | Отношение к блокировке |
|---|---|
active | Выполняется запрос (например, проведение документа 1С). Блокирует базу. |
idle | Соединение открыто пулом 1С, но запросы не идут. Все равно блокирует базу! |
idle in transaction | Транзакция открыта (BEGIN), но не закрыта (COMMIT/ROLLBACK). Критическая проблема. |
Устранение блокировок в PostgreSQL (Освобождение базы)
Сценарий 1: Принудительное завершение всех сеансов (KILL аналог из MS SQL)
Самый действенный способ для администратора — использовать системную функцию pg_terminate_backend(). Запрос необходимо выполнять, подключившись к другой базе (например, postgres).
-- Подключитесь к системной базе postgres
\c postgres
-- Отключение новых подключений к целевой базе (чтобы 1С не пересоздала их мгновенно)
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'Имя_Базы_1С';
-- Принудительное завершение (kill) всех текущих PID для указанной базы
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'Имя_Базы_1С' AND pid <> pg_backend_pid();
-- Выполнение нужной команды
DROP DATABASE "Имя_Базы_1С";Сценарий 2: Возврат базы в нормальный режим
Если вы не удаляли базу, а просто отрубали сеансы, не забудьте разрешить подключения.
UPDATE pg_database SET datallowconn = 'true' WHERE datname = 'Имя_Базы_1С';Типовые ошибки администраторов
- Выполнение DROP без запрета новых подключений (datallowconn = false): Сервер 1С обладает агрессивным пулом соединений. Как только вы убиваете PID (процесс),
rphostпонимает, что связь оборвалась, и за миллисекунды создает новое соединение. Вы не успеете написать команду DROP руками, база снова будет занята (SQL state 55006).
Тонкая настройка таймаутов (statement_timeout, idle_in_transaction_session_timeout) критична для высоконагруженных баз 1С на Linux. Эксперты ITSTM проведут тюнинг postgresql.conf, внедрят пулеры соединений (Odyssey/PgBouncer) и обеспечат бесперебойную работу СУБД.
Частые вопросы (FAQ)
В чем разница между pg_terminate_backend и pg_cancel_backend?
pg_cancel_backend только отменяет текущий выполняющийся запрос (Query), но само соединение остается открытым (переходит в idle). pg_terminate_backend жестко обрывает TCP-соединение, полностью уничтожая сессию.
Почему 1С создает так много idle соединений к PostgreSQL?
Это архитектурная особенность платформы 1С для ускорения работы. Установка нового TCP-соединения и аутентификация в СУБД — дорогая операция. 1С держит их открытыми, переиспользуя для разных пользователей (Connection Pooling).
Безопасно ли убивать соединения через pg_terminate_backend?
СУБД PostgreSQL спроектирована устойчивой (ACID). Если транзакция не была завершена (COMMIT), СУБД немедленно произведет откат (ROLLBACK). Данные в базе не повредятся, но пользователь 1С получит сообщение 'Соединение с сервером баз данных разорвано' и потеряет несохраненную работу.
Нужно ли использовать pgBouncer для 1С?
Специалисты фирмы '1С' не рекомендуют использовать внешние транзакционные пулеры (типа pgBouncer) между сервером 1С и PostgreSQL, так как 1С активно использует временные таблицы и Session Locks, логика которых ломается при смене физического коннекта в рамках одной транзакции.