Обновится ли установленный ChangeSet на стенде при его изменении
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Обновится ли установленный 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 пропустится (уже выполнена)
- Миграция 2 выполнится (новая)
Вывод
Измененный ChangeSet НЕ обновится автоматически. Золотое правило: для каждого изменения схемы создавайте новый ChangeSet. Это гарантирует консистентность и откатываемость миграций.