liquibase新增字段注释导致表格注释同时变更bug记录

liquibase是一个用于数据库变更跟踪、版本管理和自动部署的开源工具。它的使用方式方法可以参考官方文档或者其他人的博客,这里不做过多介绍。

1. 问题复现

在使用过程中发现了一个版本bug。这个bug是这样的:

当我向用户表 ts_user 增加一个字段(比如身高: height )时,我在 ts_user.xml 中填入:

<changeSet id="ts_user_02" author="lunyu">
     <addColumn tableName="ts_user">
          <column name="height" type="decimal(4,1)" remarks="身高(单位厘米)" afterColumn="phone_no"/>
     </addColumn>
 </changeSet>

当我重启项目时,日志中就发现liquibase执行了相关语句。

liquibase.executor.jvm.JdbcExecutor   - ALTER TABLE mybatis_db.ts_user ADD height DECIMAL(4, 1) NULL COMMENT '身高(单位厘米)'  AFTER `phone_no`
liquibase.executor.jvm.JdbcExecutor   - ALTER TABLE mybatis_db.ts_user COMMENT = '身高(单位厘米)'
liquibase.changelog.ChangeSet   - Columns height(decimal(4,1)) added to ts_user
liquibase.changelog.ChangeSet   - ChangeSet classpath:liquibase/changelog/sys/ts_user.xml::ts_user_02::lunyu ran successfully in 728ms

这时就发现在创建了新增了身高( height )这个字段后,liquibase莫名其妙地又给变更了一下用户( ts_user )表的注解(comment),于是我用数据库连接工具查看,用户表变成了这样:

CREATE TABLE `ts_user` (
    `id` VARCHAR(32) NOT NULL COLLATE 'utf8_unicode_ci',
    `login_name` VARCHAR(50) NULL DEFAULT NULL COMMENT '登录名' COLLATE 'utf8_unicode_ci',
    `real_name` VARCHAR(50) NULL DEFAULT NULL COMMENT '真实姓名' COLLATE 'utf8_unicode_ci',
    `ident_no` VARCHAR(18) NULL DEFAULT NULL COMMENT '身份证号' COLLATE 'utf8_unicode_ci',
    `phone_no` VARCHAR(11) NULL DEFAULT NULL COMMENT '手机号' COLLATE 'utf8_unicode_ci',
    `height` DECIMAL(4,1) NULL DEFAULT NULL COMMENT '身高(单位厘米)',
    `version` INT(11) NOT NULL DEFAULT '0' COMMENT '版本',
    `deleted` BIT(1) NOT NULL DEFAULT 'b\'0\'' COMMENT '是否删除',
    `created_by` VARCHAR(32) NOT NULL DEFAULT '-1' COMMENT '创建人' COLLATE 'utf8_unicode_ci',
    `created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_by` VARCHAR(32) NULL DEFAULT NULL COMMENT '更新人' COLLATE 'utf8_unicode_ci',
    `updated_time` DATETIME NULL DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`) USING BTREE
)
COMMENT='身高(单位厘米)'
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

很明显表注解这样的变更,影响了表的含义。

2. 问题解决

2.1. 版本替换

问题解决很简单,替换liquibase的版本。出问题的版本是3.8.9版本,把这个版本降低,使用3.6.3版本。不清楚高版本的liquibase为什么会出现这样的设计,至少我找了一圈没有找到可配置项用于消解这个问题。

使用3.6.3版本liquibase再次执行上面的步骤,执行效果如下,问题解决。

liquibase.executor.jvm.JdbcExecutor   - ALTER TABLE mybatis_db.ts_user ADD height DECIMAL(4, 1) NULL COMMENT '身高(单位厘米)'  AFTER `phone_no`
liquibase.changelog.ChangeSet   - Columns height(decimal(4,1)) added to ts_user
liquibase.changelog.ChangeSet   - ChangeSet classpath:liquibase/changelog/sys/ts_user.xml::ts_user_02::lunyu ran successfully in 1445ms

2.2. 同步重置表注释 

版本替换存在一个问题即3.6.3版本的liquibase对spring boot 2.2.9(自测目前至少是这个版本)以上版本不适配。如果选择使用高版本(2.2.9)Spring boot,则有以下变通的方法。

首先,将 databaseChangeLog 对应的 xsi:schemaLocation 标签中的值“ http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.3.xsd ”变更为3.8版本。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog 
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"
> </databaseChangeLog>

第二步,在执行的 addColumn 标签后,增加 setTableRemarks 用以重置表注释。

 <changeSet id="ts_user_02" author="lunyu">
    <addColumn tableName="ts_user">
        <column name="height" type="decimal(4,1)" remarks="身高(单位厘米)" afterColumn="phone_no"/>
    </addColumn>
    <setTableRemarks tableName="ts_user" remarks="用户表"/>
</changeSet>

增加一步设置表注释的执行动作后,重启服务执行结果如下,用户表注释又恢复正常。

liquibase.executor.jvm.JdbcExecutor   - INSERT INTO mybatis_db.DATABASECHANGELOG (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, `DESCRIPTION`, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('ts_user_01', 'lunyu', 'classpath:liquibase/changelog/sys/ts_user.xml', NOW(), 4, '8:5ba2761ed79702b6ddf312e6540dcb76', 'createTable tableName=ts_user', '', 'EXECUTED', NULL, NULL, '3.8.9', '1779819460')
liquibase.executor.jvm.JdbcExecutor   - ALTER TABLE mybatis_db.ts_user ADD height DECIMAL(4, 1) NULL COMMENT '身高(单位厘米)'  AFTER `phone_no`
liquibase.executor.jvm.JdbcExecutor   - ALTER TABLE mybatis_db.ts_user COMMENT = '身高(单位厘米)'
liquibase.changelog.ChangeSet   - Columns height(decimal(4,1)) added to ts_user
liquibase.executor.jvm.JdbcExecutor   - ALTER TABLE mybatis_db.ts_user COMMENT = '用户表'
liquibase.changelog.ChangeSet   - Remarks set on ts_user
liquibase.changelog.ChangeSet   - ChangeSet classpath:liquibase/changelog/sys/ts_user.xml::ts_user_02::lunyu ran successfully in 593ms

这样仍存在一个问题,即每次变更或新增表字段,都要在其后增加 setTableRemarks 标签用来恢复表注释,显得很冗余。

posted on 2021-09-15 15:08  论语  阅读(676)  评论(0编辑  收藏  举报

导航