← Назад к вопросам

Обновится ли установленный ChangeSet на стенде при его изменении

2.0 Middle🔥 71 комментариев
#Docker, Kubernetes и DevOps#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Обновится ли установленный ChangeSet на стенде при его изменении

Краткий ответ

Нет, не обновится автоматически. Liquibase по умолчанию НЕ пересчитывает уже выполненные ChangeSet'ы. Если ChangeSet уже был применен и записан в таблицу DATABASECHANGELOG, повторное его выполнение потребует специальных действий.

Как работает Liquibase

Liquibase отслеживает выполненные миграции в таблице DATABASECHANGELOG:

// Пример записи в DATABASECHANGELOG
// ID | AUTHOR | FILENAME | DATEEXECUTED | ORDEREXECUTED | EXECTYPE | MD5SUM | ...
// 1  | user   | changelog.xml | 2024-01-15 | 1 | EXECUTED | abc123def... | ...

Каждый ChangeSet идентифицируется комбинацией: id + author + filename. Если эта комбинация уже в таблице, Liquibase пропускает этот ChangeSet.

Проблема: Изменение выполненного ChangeSet

<!-- changelog.xml (версия 1) -->
<changeSet id="1" author="user">
    <createTable tableName="users">
        <column name="id" type="int" autoIncrement="true" />
        <column name="name" type="varchar(100)" />
    </createTable>
</changeSet>

<!-- Позже вы измените содержимое (версия 2) -->
<changeSet id="1" author="user">
    <createTable tableName="users">
        <column name="id" type="int" autoIncrement="true" />
        <column name="name" type="varchar(100)" />
        <column name="email" type="varchar(100)" />  <!-- НОВОЕ ПОЛЕ -->
    </createTable>
</changeSet>

Результат: База останется в состоянии версии 1 (только 2 колонки), новое поле НЕ добавится.

Решение 1: Использовать runOnChange="true"

<changeSet id="1" author="user" runOnChange="true">
    <createTable tableName="users">
        <column name="id" type="int" autoIncrement="true" />
        <column name="name" type="varchar(100)" />
        <column name="email" type="varchar(100)" />
    </createTable>
</changeSet>

Плюсы:

  • ChangeSet перевыполняется при каждом изменении содержимого

Минусы:

  • Рискованно для idempotent операций (CREATE TABLE упадет при повторном выполнении)
  • Используй только для ALTER, DROP или скриптов, которые безопасны при переповторе

Решение 2: Новый ChangeSet (РЕКОМЕНДУЕТСЯ)

<changeSet id="1" author="user">
    <createTable tableName="users">
        <column name="id" type="int" autoIncrement="true" />
        <column name="name" type="varchar(100)" />
    </createTable>
</changeSet>

<changeSet id="2" author="user">
    <addColumn tableName="users">
        <column name="email" type="varchar(100)" />
    </addColumn>
</changeSet>

Плюсы:

  • Чистая история миграций
  • Безопасно откатывать
  • Отслеживает каждый шаг эволюции схемы

Минусы:

  • Требует создания нового ChangeSet

Решение 3: Перейти на более новый MD5SUM

Если вы поменяли содержимое и хотите переписать историю (ТОЛЬКО В DEVELOPMENT!):

-- Удалить запись из DATABASECHANGELOG
DELETE FROM DATABASECHANGELOG WHERE ID = '1' AND AUTHOR = 'user';

WARNING: Это опасно в production и нарушает историю миграций.

Best Practices

  • НИКОГДА не изменяйте уже выполненные ChangeSet'ы в production
  • Создавайте новые ChangeSet'ы для любых изменений
  • Используйте runOnChange="true" только для скриптов, которые idempotent (безопасны при переповторе)
  • Версионируйте changelog как обычный код в git
  • Проверяйте changelog перед коммитом в production

Практический пример

<!-- changlog.xml -->
<databaseChangeLog>
    <!-- Миграция 1 (executed) -->
    <changeSet id="001-create-users" author="dev">
        <createTable tableName="users">
            <column name="id" type="bigint" autoIncrement="true" primaryKey="true" />
            <column name="username" type="varchar(100)" unique="true" />
        </createTable>
    </changeSet>

    <!-- Миграция 2 (новая) -->
    <changeSet id="002-add-email-to-users" author="dev">
        <addColumn tableName="users">
            <column name="email" type="varchar(100)" unique="true" />
        </addColumn>
    </changeSet>
</databaseChangeLog>

При запуске Liquibase:

  1. Миграция 1 пропустится (уже выполнена)
  2. Миграция 2 выполнится (новая)

Вывод

Измененный ChangeSet НЕ обновится автоматически. Золотое правило: для каждого изменения схемы создавайте новый ChangeSet. Это гарантирует консистентность и откатываемость миграций.

Обновится ли установленный ChangeSet на стенде при его изменении | PrepBro