Как Liquibase работает с несколькими экземплярами приложения (кластер)?
В кластерном окружении Liquibase использует таблицу DATABASECHANGELOGLOCK для предотвращения одновременного выполнения миграций несколькими экземплярами.
Механизм блокировки
- Перед началом миграции экземпляр пытается установить блокировку (
LOCKED = true) - Если блокировка уже установлена другим экземпляром — текущий экземпляр ждёт (по умолчанию до 5 минут)
- После завершения миграции блокировка снимается (
LOCKED = false) - Остальные экземпляры обнаруживают, что все changeset-ы уже применены, и стартуют нормально
Возможные проблемы
Зависшая блокировка — если экземпляр аварийно завершился во время миграции, блокировка остаётся. Решение:
Пример
liquibase releaseLocks
Или SQL:
Пример
UPDATE DATABASECHANGELOGLOCK SET LOCKED = FALSE WHERE ID = 1;
Таймаут ожидания — если блокировка держится слишком долго, другие экземпляры не смогут стартовать. Настройка таймаута:
Пример
spring.liquibase.lock-wait-time=300
Рекомендации
В банковских системах предпочтительнее выполнять миграции отдельным шагом до деплоя, а не при старте приложения. Это позволяет:
- Избежать проблем с блокировками в кластере
- Контролировать момент применения миграций
- Быстрее откатить изменения при проблемах
На собеседовании: интервьюер проверяет понимание проблем конкурентного доступа. Нужно объяснить механизм DATABASECHANGELOGLOCK и знать, что делать при зависшей блокировке. Частая ошибка — предлагать запускать миграции при старте каждого экземпляра, не понимая, что это создаёт проблему блокировок.