You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Liquibase已执行变更集重复执行:删除表后原表重现

Liquibase拆分变更文件后重复执行同一ID变更集的问题

问题背景

我们使用Liquibase进行数据库变更部署,最初通过init_2023.yaml文件执行了FOOBAR表创建(FOOBAR-1)、唯一索引创建(FOOBAR-2)、唯一约束添加(FOOBAR-3)等变更集,执行正常。

为实现表独立版本管理,我们将init_2023.yaml拆分为按表命名的foobar.yaml,并新增删除FOOBAR表的变更集FOOBAR-4。执行该文件后表被正常删除,但重新导入时,Liquibase再次执行FOOBAR-1、FOOBAR-2、FOOBAR-3,导致已删除的表重现。

查看DATABASECHANGLOG表发现,这些变更集分别以init_2023.yaml和foobar.yaml为文件名记录了两次执行记录。我们预期同一ID的变更集不会重复执行,想确认是否与文件名有关,以及如何避免该问题。

相关变更集代码

原init_2023.yaml中的变更集(拆分后移入foobar.yaml)

databaseChangeLog:
- changeSet:
    id: FOOBAR-1
    failOnError: false
    author: anyA
    changes:
    - createTable:
        columns:
        - column:
            constraints:
              nullable: false
            name: COLA
            type: VARCHAR2(1000 BYTE)
        - column:
            name: COLB
            type: VARCHAR2(1000 BYTE)
        - column:
            name: VOLC
            type: VARCHAR2(1000 BYTE)
        - column:
            name: COLD
            type: VARCHAR2(1000 BYTE)
        tableName: FOOBAR
- changeSet:
    id: FOOBAR-2
    failOnError: false
    author: anyA
    changes:
    - createIndex:
        columns:
        - column:
            name: COLA
        indexName: FOOBAR_PK
        tableName: FOOBAR
        unique: true
- changeSet:
    id: FOOBAR-3
    failOnError: false
    author: anyA
    changes:
    - addUniqueConstraint:
        columnNames: COLA
        constraintName: FOOBAR_PK
        forIndexName: FOOBAR_PK
        tableName: FOOBAR

foobar.yaml新增的变更集

- changeSet:
    id: FOOBAR-4
    failOnError: false
    author: anyB
    changes:
    - dropTable:
        cascadeConstraints: true
        tableName: FOOBAR

DATABASECHANGLOG表记录

|    ID    | AUTHOR |  FILENAME      |    DATEEXECUTED     | ORDEREXECUTED |       MD5SUM        | DEPLOYMENT_ID
| -------- | ------ | -------------- | ------------------- | ------------- | ------------------- |
| FOOBAR-3 | anyA   | foobar.yaml    | 23.10.2023 12:00:00 | 517           | 8:foobar3md5sum_abc | 63
| FOOBAR-2 | anyA   | foobar.yaml    | 23.10.2023 12:00:00 | 516           | 8:foobar2md5sum_def | 63
| FOOBAR-1 | anyA   | foobar.yaml    | 23.10.2023 12:00:00 | 515           | 8:foobar1md5sum_ghi | 63
| FOOBAR-4 | anyB   | foobar.yaml    | 23.10.2023 11:00:00 | 504           | 8:foobar2md5sum_def | 52
| FOOBAR-3 | anyA   | init_2023.yaml | 01.09.2023 12:00:00 | 103           | 8:foobar3md5sum_abc | 11
| FOOBAR-2 | anyA   | init_2023.yaml | 01.09.2023 12:00:00 | 102           | 8:foobar2md5sum_def | 11
| FOOBAR-1 | anyA   | init_2023.yaml | 01.09.2023 12:00:00 | 101           | 8:foobar1md5sum_ghi | 11

原因分析

Liquibase判断变更集是否已执行的唯一标识是ID + AUTHOR + FILENAME的组合,而非仅依赖ID。当你把变更集从init_2023.yaml迁移到foobar.yaml后,FILENAME字段发生变化,Liquibase会将这些变更集视为全新的未执行项,因此会重复执行。

解决方案

方案1:用addchangeloglock标记历史执行记录

在foobar.yaml中添加变更集,将原init_2023.yaml中的FOOBAR-1/2/3标记为已执行,避免Liquibase重复运行:

- changeSet:
    id: FOOBAR-mark-history-executed
    author: anyA
    changes:
    - addchangeloglock:
        id: FOOBAR-1
        author: anyA
        filename: init_2023.yaml
    - addchangeloglock:
        id: FOOBAR-2
        author: anyA
        filename: init_2023.yaml
    - addchangeloglock:
        id: FOOBAR-3
        author: anyA
        filename: init_2023.yaml

执行该变更集后,Liquibase会更新DATABASECHANGLOG的执行状态,后续运行foobar.yaml时会自动跳过FOOBAR-1/2/3。

方案2:手动修改DATABASECHANGLOG记录(不推荐)

直接更新数据库中的DATABASECHANGLOG表,将原记录的FILENAME从init_2023.yaml改为foobar.yaml。此方法需直接操作数据库,风险较高,仅适合测试环境或紧急场景。

方案3:重新设计变更集ID(长期推荐)

后续拆分变更文件时,为变更集分配唯一ID(例如在原ID后追加文件标识,如FOOBAR-1-foobar),避免同一ID出现在不同文件中。这能从根源上规避此类问题,更符合Liquibase的设计规范。

内容的提问来源于stack exchange,提问作者MKochenburger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:13:15