news 2026/10/14 1:52:45

数据库版本混乱?Liquibase 自动迁移 + contexts 裁剪,qkl-boot 这么管的

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据库版本混乱?Liquibase 自动迁移 + contexts 裁剪,qkl-boot 这么管的

数据库版本混乱?Liquibase 自动迁移 + contexts 裁剪,qkl-boot 这么管的

导读:新同事拉代码一启动,表没建、字段没加、索引没配,报错信息五花八门——这种痛在多人协作项目里太常见了。qkl-boot 的做法是启动时用 Liquibase 自动建表迁移,配合 LIQUIBASE_CONTEXTS 按模块和环境裁剪,不用手工灌任何 SQL。

先说结论:数据库结构变更,千万别靠"谁改了谁手动执行一下 SQL"这种约定。人一定会忘,忘了就炸,炸了还得考古 git 找哪条没执行。Liquibase 的核心思路是:每个结构变更都是一个带唯一标识的 changeset,数据库里记录哪些已执行,启动时自动补齐没跑的。幂等、可回滚、可审计,一套下来数据库变更就和代码一样有版本了。

changeset 怎么写:一个文件管一张表

qkl-boot 的变更文件放在classpath:db/下,主文件master.yaml用 includeAll 把所有分文件拉进来。每个 changeset 必须有id+author,这是它在数据库里的"身份证":

# db/changelog/20261001-init-settlement.xml

id我习惯直接用日期+序号(20261001-001),谁在什么时候加的,git log 一对照就清楚。改已发布的 changeset 是大忌——改了内容但 id 没变,Liquibase 认为它已经执行过,你的修改永远不会生效,还会误导后来的人。真要改,就加一个新的 changeset 做补偿修改。

按模块裁剪:contexts 是开关

qkl-boot 最实用的设计是模块裁剪:demo、ai、finance、print 这些可选模块,不只要在代码和 Maven Profile 层面裁剪,数据库表也得跟着裁——不然关掉 ai 模块,库里还躺着 ai 的表,没意义。Liquibase 的context就是干这个的:

# db/changelog/20261002-init-ai.xml(AI 模块专用)

启动时通过环境变量/配置指定激活哪些 context,多个用逗号分隔:

# 只跑基础 + finance 模块的表LIQUIBASE_CONTEXTS=base,finance mvn-plqkl-bootstrap-amspring-boot:run# 全量(本地开发常用)LIQUIBASE_CONTEXTS=base,ai,finance,print,channel,notify mvn-plqkl-bootstrap-amspring-boot:run
# application.ymlspring:liquibase:enabled:truechange-log:classpath:db/master.yamlcontexts:${LIQUIBASE_CONTEXTS:base}# 默认只跑基础模块default-schema:qkl_boot

配合 Maven Profile 一起用:-Pno-ai时配置里不带aicontext,AI 模块的表就不建。代码、依赖、表结构三层一起裁,才是真正干净的模块化。

踩坑实录:启动直接报 “Table already exists”

现象:在已跑过老版本的库上直接升级到新代码,启动报错:

liquibase.exception.ValidationFailedException: Validation Failed: 1 changesets check failed changeSet classpath:db/master.yaml::20260901-003::qkl Reason: liquibase.exception.DatabaseException: Table 'sys_user' already exists

排查过程:先查DATABASECHANGELOG表——这是 Liquibase 自己的记录表,看 20260901-003 到底执行过没有。结果发现库里sys_user表是老同事手工建的(SHOW CREATE TABLE的时间戳和字段都对得上),但DATABASECHANGELOG里根本没有这条记录。也就是说:表存在,但 Liquibase 不认账,启动时想再建一遍,直接撞车。

定位思路:这是"历史遗留手工 SQL + 新上 Liquibase"的典型冲突。Liquibase 只认自己的变更记录,库里的表是"黑户"。直接删表重来不现实(有数据),改 changeset 的 id 也不对(治标不治本,还会污染变更历史)。

最终解决:把手工建的表"补录"成已执行状态——用changelogSync让 Liquibase 把现有 changeset 标记为已应用,不真正执行 SQL:

# 只标记不执行:把当前变更文件里的 changeset 全部记入 DATABASECHANGELOGmvn liquibase:changelogSync\-Dliquibase.changeLogFile=db/master.yaml\-Dliquibase.defaultSchemaName=qkl_boot

跑完再启动,Liquibase 认为所有 changeset 已执行,跳过建表,正常进入后续迁移。一次性操作,别在正常流程里用——它会把所有变更都标记为已执行,新加的 changeset 也会被跳过。

生产补丁怎么打:新增 changeset,别改旧的

上线后要加个索引,很多人的第一反应是打开之前的 changeset 把 createIndex 塞进去。千万别——那条 changeset 已经在生产执行过了,Liquibase 不会重跑,你的索引永远不会建出来,而且别人 review 变更记录时还以为索引早就有了,排查慢查询时白折腾半天。正确的姿势永远是新增:

# 生产环境只应用这一个补丁(--tag 是可选的安全标记)mvn liquibase:update\-Dliquibase.changeLogFile=db/master.yaml\-Dliquibase.defaultSchemaName=qkl_boot\-Dliquibase.contexts=base

跑完SELECT * FROM DATABASECHANGELOG ORDER BY DATEEXECUTED DESC LIMIT 5;确认新 changeset 已记录。这个习惯养成了,生产变更就有了完整的审计链——哪天出问题,谁加的、什么时候加的、加的什么,一条 SQL 查清楚。

还有几个容易踩的点

  • 多个开发分支并行时 changeset 冲突。两个人都在 20261013 加了 changeset,id 撞了,后 merge 的人启动就报 duplicate。约定:id 里带上自己名字缩写或 JIRA 号,比如20261013-qkl-001,从根上避免撞车。
  • 线上变更用--changelogFile打补丁,别改已发布 changeset。生产环境加索引、加字段,一律新增 changeset,不要回头编辑旧的。
  • 非 SQL 变更类型要小心。sqlFile类型执行任意 SQL,在 Oracle/MySQL 方言差异下容易翻车,能用 createTable/addColumn 等原生标签就用原生标签,跨库兼容性更好。

可以直接抄的结论

  1. 每个结构变更是带唯一 id 的 changeset,id用"日期+作者+序号",已发布的 changeset 永不修改;
  2. master.yamlincludeAll 管总入口,按模块加context,配合LIQUIBASE_CONTEXTS裁剪表结构;
  3. 老库升级用changelogSync把手工 SQL 的表补录进变更记录,一次性操作;
  4. 分支并行约定 id 防冲突;生产打补丁一律新增 changeset;
  5. 首次启动自动建表后,不要再手工灌 SQL,否则和 Liquibase 的记录对不上。

数据库变更和代码一样,也要"可追溯、可回滚"。Liquibase 这套跑顺了,新同事拉代码一条命令就能起来,省下的都是互相猜疑的时间。

项目源码:https://gitee.com/gzqkl/qkl-boot

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 1:52:03

截图自动导入Excel:PowerShell、VBA与openpyxl批量处理实战

简介:面向日常办公中需要频繁将截图整理进Excel报表的人群,这份docx文档给出了一种低门槛、可复用的批量截图与自动导入方案。资源从小工具选型入手,讲解了SuperCapture与Excel工具箱的搭配使用,涵盖固定区域截图、图片自动命名、…

作者头像 李华
网站建设 2026/10/14 1:51:50

《影之刃零》Boss的数量已经确定为50多个,其中30多种主要武器都是通过打败这些Boss才能获得,在10月29日将会正式发售

距离10月29日发售只有半个月的时间,《影之刃零》的制作人梁其伟在接受4Gamer集体采访时透露出一个真实的数字:本作中Boss的数量至少有50个,并且应该不止于此。他给出这个下限的理由很简单——游戏中有30种主武器和大约20种副武器,…

作者头像 李华
网站建设 2026/10/14 1:50:52

Modbus功能码实战指南:从存储区到报文排错一次讲透

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 1:50:18

AI提示词大全基础版:五要素与场景化模板,让大模型输出不废话

简介:《AI提示词大全》基础版是一份面向AI语言模型使用者的提示词参考资料,适合AIGC学习者、内容创作者及希望提升人机协作效率的职场人士。文档围绕提示词的多样化应用展开,汇集写作助理、提示词修改器、提示词生成器、英语翻译与润色、论文…

作者头像 李华