Почему измененный ChangeSet в Liquibase не применяется повторно на стенде?

«Почему измененный ChangeSet в Liquibase не применяется повторно на стенде?» — вопрос из категории DevOps, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Liquibase выполняет каждый ChangeSet только один раз. Если ChangeSet уже был применен к БД, его повторное выполнение при изменении исходного кода не произойдет автоматически. Это механизм идемпотентности.

Основные причины и решения:

Причина Решение
1. Изменение checksum Liquibase хранит хэш (checksum) ChangeSet в таблице DATABASECHANGELOG. При изменении скрипта checksum не совпадает, и Liquibase отказывается выполнять ChangeSet, считая его измененным после применения.
2. ChangeSet не помечен для повторного запуска Используйте атрибут runOnChange="true". Тогда ChangeSet будет повторно выполняться при каждом изменении его содержимого.
3. Необходимость принудительного перезапуска Измените id или author ChangeSet. Это заставит Liquibase воспринять его как новый.

Пример настройки ChangeSet для повторного выполнения при изменениях:

<changeSet id="add-email-column" author="dev" runOnChange="true">
    <addColumn tableName="users">
        <column name="email" type="varchar(255)"/>
    </addColumn>
</changeSet>

Дополнительные шаги для диагностики:

  1. Проверить таблицу DATABASECHANGELOG: Убедитесь, что ChangeSet записан и его MD5SUM соответствует текущему состоянию.
  2. Сбросить checksum (осторожно!): Команда liquibase clearCheckSums сбросит все checksums, и при следующем запуске Liquibase пересчитает их. Используйте только в тестовых средах.
  3. Проверить логи Liquibase: Включите детальное логирование (logging.level.liquibase=DEBUG в Spring) для просмотра процесса валидации checksums.
  4. Убедиться в автоматическом запуске: Проверьте конфигурацию (например, spring.liquibase.enabled=true и spring.liquibase.change-log в Spring Boot).

Важно: Стратегия runOnChange="true" подходит для изменяемых справочных данных или условий. Для структурных изменений (DDL) чаще создают новый ChangeSet с другим id.