Возможно ли автоматически снять блокировку в PostgreSQL?
-
19-09-2019 - |
Вопрос
Я тестирую отказоустойчивость системы ActiveMQ, настроенной как JDBC Master / Slave.В этой настройке есть одна база данных postgres и два брокера - один является главным брокером, другой - подчиненным брокером.Способ работы этого механизма заключается в том, что мастер устанавливает эксклюзивную блокировку для таблицы в базе данных.Ведомое устройство также пытается сделать это и ждет, пока блокировка не станет доступной.Если ведущий умирает, блокировка должна быть снята, и ведомый возьмет верх.Однако, если мастер теряет сетевое подключение к базе данных, блокировка никогда не снимается, что приводит к сценарию взаимоблокировки.Что, по-видимому, требуется здесь, так это способ сообщить Postgres автоматически снять блокировку, если она не будет продлена в течение указанного периода времени.Книга шаблонов проектирования POSA 3 называет это шаблоном лизинга.Можно ли заставить Postgres сделать это?Если нет, поддерживают ли это другие поставщики баз данных?
Решение
Это не тупиковая ситуация, это проблема с потерянным соединением.
Взаимоблокировка возникает, когда две транзакции пытаются заблокировать ресурсы, ранее заблокированные друг другом. PostgreSQL
обнаруживает эти ситуации.
В вашем случае, master
блокирует ресурс, slave
ждет master
, и master
ожидает ввода данных пользователем, который он никогда не получает, потому что соединение потеряно.
Всякий раз , когда PostgreSQL
обнаруживая потерянное соединение, он автоматически откатывает свою транзакцию.
Чтобы управлять обнаружением потери соединения, вы можете использовать следующее PostgreSQL
варианты подключения:
tcp_keepalives_idle (integer)
В системах, поддерживающих
TCP_KEEPIDLE
параметр сокета, указывает количество секунд между отправкой сохраненных данных при неработающем соединении в противном случае.При нулевом значении используется системное значение по умолчанию.ЕслиTCP_KEEPIDLE
не поддерживается, этот параметр должен быть равен нулю.Этот параметр игнорируется для соединений, выполняемых через сокет Unix-домена.
tcp_keepalives_interval (integer)
В системах, поддерживающих
TCP_KEEPINTVL
параметр сокета, указывает, как долго, в секундах, ждать ответа на keepalive перед повторной передачей.При нулевом значении используется системное значение по умолчанию.ЕслиTCP_KEEPINTVL
не поддерживается, этот параметр должен быть равен нулю.Этот параметр игнорируется для соединений, выполняемых через сокет Unix-домена.
tcp_keepalives_count (integer)
В системах, поддерживающих
TCP_KEEPCNT
параметр сокета, указывает, сколько сохранений может быть потеряно, прежде чем соединение будет считаться разорванным.При нулевом значении используется системное значение по умолчанию.ЕслиTCP_KEEPCNT
не поддерживается, этот параметр должен быть равен нулю.Этот параметр игнорируется для соединений, выполняемых через сокет Unix-домена.