Liquibase ChangeLog 和 LogLock table 在后期创建而不会使已经执行的脚本失败

Liquibase ChangeLog and LogLock table creation on Later stage without failing already executed scripts

我有一个 微服务 运行 很久以前我们意识到 自定义 changelogchangeloglock 表定义不正确。见下文...

spring:
    liquibase:
        abc:
            change-log: classpath:/liquibase/changelog.yml
            database-change-log-table: CUSTOM_CHANGE_LOG
            database-change-log-lock-table: CUSTOM_CHANGE_LOG_LOCK

abc 被添加到正确的路径之间,我们已经执行了几乎 18 个脚本 并且已经登录到 master表格 DATABASECHANGELOGDATABASECHANGELOGLOCK .

因此,如果我根据以下内容更正 yml 中的路径

spring:
    liquibase:
        change-log: classpath:/liquibase/changelog.yml
        database-change-log-table: CUSTOM_CHANGE_LOG
        database-change-log-lock-table: CUSTOM_CHANGE_LOG_LOCK

然后它会继续执行所有旧的18个脚本,这将导致失败。 如何解决?

此外,我不确定它是否会自动创建自定义表格,还是我需要手动创建这些表格?

如能为 both the points 提供任何帮助,我们将不胜感激。如果您需要更多详细信息,请发表评论

如果我正确理解你的问题,有两种选择:

  1. preConditions 写入您现有的变更集并指定 onFail="MARK_RAN" 属性。这样,您的所有变更集都将在 preConditions 上失败,并在 CUSTOM_CHANGE_LOG table 中标记为 运行。您的应用程序将成功启动。

  2. 指定CUSTOM_CHANGE_LOG table并从databasechangelog复制所有数据。

用于将数据从 table 复制到 table 的 ChangeSet 可能如下所示:

<changeSet id="foo" author="bar">
    <preConditions onFail="MARK_RAN">
        <tableExists tableName="databasechangelog"/>
        <tableExists tableName="CUSTOM_CHANGE_LOG"/>
        <sqlCheck expecterResult="0">
            SELECT COUNT(*) FROM databasechangelog; 
        </sqlCheck>
    </preConditions>
    <sql>
        INSERT INTO CUSTOM_CHANGE_LOG (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, EXECTYPE, MD5SUM, DESCRIPTION, COMMENTS, TAG, LIQUIBASE, CONTEXTS, LABELS, DEPLOYMENT_ID)
        SELECT ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, EXECTYPE, MD5SUM, DESCRIPTION, COMMENTS, TAG, LIQUIBASE, CONTEXTS, LABELS, DEPLOYMENT_ID
        FROM databasechangelog
    </sql>
</changeSet>

这个changeSet应该是应用程序启动时最先执行的。所以你应该把这个 changeSet 放在你的 changeLog 中的所有其他 changeSets 之前。复制所有数据后,liquibase 应将所有现有的变更集视为已执行。


我会使用选项 #1,因为无论如何你的 changeSets 应该有先决条件。

此问题已解决。有两种方法可以 w/o 运行 使用任何手动脚本。但我更喜欢下面一个

我们将 不在 application.yml 中输入任何自定义 table 但会在更新日志中添加新查询.

changeset 看起来像这样

- changeSet:
      id: your-id-here
      author: kunal-vohra
      #dbms: oracle #if you want it to run db specific then uncomment
      changes:
        - sqlFile:
            encoding: utf8
            path: ./liquibase/changes/sql-file-name.sql

sql-file-name.sql 看起来像

declare
begin
  execute immediate 'CREATE TABLE CUSTOM_CHANGE_LOG AS SELECT * FROM DATABASECHANGELOG WHERE AUTHOR = ''kunal-vohra''';
  exception when others then
    if SQLCODE = -955 then null; else raise; end if;
    UPDATE CUSTOM_CHANGE_LOG  SET MD5SUM = null;
end;
/

上面查询中发生的事情是,如果 table 已经创建,那么它不会创建新的 table,否则它会创建。

然后它正在丢弃所有 **HASH**

然后在 application.yml

中提出第二个 PR 并进行更改
spring:
    liquibase:
        change-log: classpath:/liquibase/changelog.yml
        database-change-log-table: CUSTOM_CHANGE_LOG
        database-change-log-lock-table: CUSTOM_CHANGE_LOG_LOCK

我们在这里的主要好处是我们不必 运行 在 PROD 上手动进行任何操作。

如果您想在一个 PR 中执行上述操作 另一种方法是 只需将 changeset 移动到文件顶部而不是下面。