Gymterview
senior

Как Liquibase работает с несколькими экземплярами приложения (кластер)?

В кластерном окружении Liquibase использует таблицу DATABASECHANGELOGLOCK для предотвращения одновременного выполнения миграций несколькими экземплярами.

Механизм блокировки

  1. Перед началом миграции экземпляр пытается установить блокировку (LOCKED = true)
  2. Если блокировка уже установлена другим экземпляром — текущий экземпляр ждёт (по умолчанию до 5 минут)
  3. После завершения миграции блокировка снимается (LOCKED = false)
  4. Остальные экземпляры обнаруживают, что все changeset-ы уже применены, и стартуют нормально

Возможные проблемы

Зависшая блокировка — если экземпляр аварийно завершился во время миграции, блокировка остаётся. Решение:

Пример
liquibase releaseLocks

Или SQL:

Пример
UPDATE DATABASECHANGELOGLOCK SET LOCKED = FALSE WHERE ID = 1;

Таймаут ожидания — если блокировка держится слишком долго, другие экземпляры не смогут стартовать. Настройка таймаута:

Пример
spring.liquibase.lock-wait-time=300

Рекомендации

В банковских системах предпочтительнее выполнять миграции отдельным шагом до деплоя, а не при старте приложения. Это позволяет:

  • Избежать проблем с блокировками в кластере
  • Контролировать момент применения миграций
  • Быстрее откатить изменения при проблемах

На собеседовании: интервьюер проверяет понимание проблем конкурентного доступа. Нужно объяснить механизм DATABASECHANGELOGLOCK и знать, что делать при зависшей блокировке. Частая ошибка — предлагать запускать миграции при старте каждого экземпляра, не понимая, что это создаёт проблему блокировок.