找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5330

积分

0

好友

734

主题
发表于 3 小时前 | 查看: 2| 回复: 0

在项目开发中,我们对代码通常已经有比较成熟的管理方式:提交到 Git,功能分支走 Review,发布依赖流水线,线上问题可以通过提交记录追踪。

但是数据库变更呢?

很多团队一开始可能还是比较原始的方式:开发写一段 SQL,发到群里;测试环境手动执行一次;预发环境再执行一次;上线时 DBA 或开发再连到生产库执行一次。

这种方式短期看很方便,但问题也很明显:

  • 哪些 SQL 执行过,依赖人工记忆;
  • 测试、预发、生产环境容易不一致;
  • SQL 文件散落在群聊、文档、本地目录里;
  • 线上数据库需要人工直连操作;
  • 出问题后,很难追踪这次变更是谁加的、什么时候执行的、在哪个环境执行过。

Liquibase 要解决的,正是这些问题。它的核心价值不是"帮我们执行 SQL",而是让数据库变更像代码一样进入工程化管理。在云栈社区的技术讨论中,数据库版本管理一直是团队协作中的高频痛点。

一、Liquibase 到底是什么?

Liquibase 是一个数据库变更管理工具。它可以把数据库表结构变更、索引变更、初始化数据、数据修复脚本等内容,统一放到版本管理中,并通过固定流程执行到目标数据库。

实际使用中,我们并不是一定要把所有 SQL 都改写成复杂的 YAML 或 XML 结构。很多项目里,最自然的方式就是:继续写 SQL,但把 SQL 放进 Liquibase 的 changeSet 里。

例如下面这种形式:

<changeSet id="2026-003-create-blog-image" author="test">
    <sql>
        CREATE TABLE `blog_image` (
            `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
            `account` VARCHAR(64) NOT NULL COMMENT '上传者账号',
            `original_name` VARCHAR(255) DEFAULT NULL COMMENT '原始文件名',
            `file_name` VARCHAR(255) NOT NULL COMMENT '存储文件名',
            `file_path` VARCHAR(500) NOT NULL COMMENT '文件存储路径',
            `image_url` VARCHAR(500) NOT NULL COMMENT '图片访问URL',
            `file_size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)',
            `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
            PRIMARY KEY (`id`),
            KEY `idx_account` (`account`),
            KEY `idx_create_time` (`create_time`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图片上传记录表';
    </sql>
</changeSet>

这其实很适合团队落地。开发仍然可以用自己熟悉的 SQL 表达数据库变更,但这段 SQL 不再是一个孤立脚本,而是变成了一个有编号、有作者、有执行记录的受控变更。

二、为什么要用 Liquibase?

我觉得 Liquibase 最重要的几个关键词是:可控、可追溯、可重复、可集成。

1. 可控:不再随手直连线上库改表

数据库变更最怕的不是写 SQL,而是执行过程失控。如果开发、测试、运维都可以在不同环境里手动执行 SQL,那么环境很容易出现差异。更严重的是,线上数据库被人工直接修改后,代码仓库里可能根本没有留下对应记录。

使用 Liquibase 后,数据库变更通常会变成这样的流程:

  1. 开发编写 changeSet;
  2. changeSet 随代码一起提交;
  3. 代码 Review 时一起审查数据库变更;
  4. 测试环境通过 Liquibase 执行;
  5. 预发、生产环境通过发布流程执行;
  6. 执行结果记录在数据库中。

也就是说,生产库不是不能变,而是不能绕过流程随意变。数据库变更从"人连上去执行 SQL",变成"变更文件进入仓库,由发布流程执行"。这就是可控。

2. 可追溯:每一次数据库变更都有记录

Liquibase 会在数据库中维护一张核心表:DATABASECHANGELOG

这张表会记录每个已经执行过的 changeSet,包括:

  • changeSet 的 id;
  • author;
  • 文件路径;
  • 执行时间;
  • 执行顺序;
  • checksum;
  • 执行状态。

所以当我们想知道某个库是否执行过某次变更时,不需要靠猜,也不需要去翻群聊,只要看 DATABASECHANGELOG 就可以。比如某张表什么时候创建的,某个字段是不是已经加过,某个索引在哪个版本上线,都可以通过这张表追踪。

Liquibase DATABASECHANGELOG 表数据记录,显示变更ID、作者、文件名、执行时间、顺序、执行状态和MD5校验和

3. 可重复:新环境初始化更轻松

很多项目都有一个痛点:老环境能跑,新环境搭不起来。原因往往是数据库结构没有完整沉淀下来。项目跑了几年之后,建表 SQL、字段修改 SQL、初始化数据散落在不同地方,新人或新环境想从零搭建数据库,非常痛苦。

Liquibase 的好处是,所有数据库演进历史都在 changelog 里。一个新环境只要配置好数据库连接,执行 Liquibase,就可以按照历史顺序把数据库结构一步步构建出来。这对于本地开发环境、测试环境、临时演示环境、自动化测试环境都很有帮助。

4. 可集成:适合放进 CI/CD 流程

Liquibase 可以通过命令行、Maven、Gradle、Spring Boot、Jenkins、GitHub Actions 等方式集成到发布流程中。在 Spring Boot 项目里,比较常见的方式是应用启动时自动执行 Liquibase。

配置示例:

spring:
  liquibase:
    enabled: true
    change-log: classpath:liquibase/master.xml

主 changelog 文件负责组织具体变更:

Liquibase 项目资源目录结构,展示 master.xml 和按年份版本命名的具体变更文件

这样数据库变更就可以跟随应用版本一起发布,而不是靠上线前临时执行一堆 SQL。

三、Liquibase 是怎么运转的?

Liquibase 的运行逻辑其实不复杂。可以简单理解成:

读取 changelog 文件
        ↓
连接目标数据库
        ↓
检查 DATABASECHANGELOGLOCK
        ↓
读取 DATABASECHANGELOG
        ↓
判断哪些 changeSet 没执行过
        ↓
按顺序执行未执行的 changeSet
        ↓
执行成功后写入记录
        ↓
释放锁

这里有两张表比较关键。

DATABASECHANGELOG

这张表负责记录"哪些变更已经执行过"。Liquibase 判断一个 changeSet 是否执行过,主要看:id + author + file path

如果数据库里没有这条记录,就执行;如果已经有记录,就不会重复执行。如果已经执行过,但文件内容被改了,checksum 对不上,Liquibase 通常会报错。这也是它防止历史变更被偷偷修改的重要机制。

DATABASECHANGELOGLOCK

这张表负责加锁。在某些场景下,可能会有多个应用实例同时启动。如果它们都尝试执行 Liquibase,就可能产生并发执行数据库变更的问题。DATABASECHANGELOGLOCK 的作用就是保证同一时间只有一个 Liquibase 实例在执行变更。

四、如何接入和使用 Liquibase?

下面以 Spring Boot 项目为例,介绍 Liquibase 的基本接入方式。

1. 引入 Maven 依赖

pom.xml 中加入 Liquibase 依赖:

<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
</dependency>

如果项目使用的是 MySQL,还需要确保已经引入 MySQL 驱动:

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
</dependency>

Spring Boot 会自动识别 Liquibase,并在应用启动时根据配置执行数据库变更。

2. 添加 Liquibase 配置

application.yml 中增加配置:

spring:
  liquibase:
    enabled: true
    change-log: classpath:liquibase/master.xml

其中:

  • enabled: true 表示启用 Liquibase;
  • change-log 指定 Liquibase 的主变更文件。

如果不同环境有不同策略,也可以在不同配置文件中控制是否启用:

spring:
  liquibase:
    enabled: false

例如本地环境启用,某些特殊测试场景关闭,或者生产环境统一由流水线单独执行。

3. 创建 changelog 目录

推荐目录结构如下:

src/main/resources
└── liquibase
    └── master.xml
    └── db
        ├── 2026-001-create-user.xml
        ├── 2026-002-create-blog.xml
        └── 2026-003-create-blog-image.xml

主文件 master.xml 只负责组织各个变更文件:

<?xml version="1.0" encoding="UTF-8"?>
<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-latest.xsd">

    <include file="db/2026-001-create-user.xml"/>
    <include file="db/2026-002-create-blog.xml"/>
    <include file="db/2026-003-create-blog-image.xml"/>

</databaseChangeLog>

这样做的好处是结构清晰,每次数据库变更都有独立文件,后续维护和排查都更方便。

4. 编写 changeSet

实际项目中,可以直接把 SQL 写在 <sql> 标签中。例如创建图片上传记录表:

<?xml version="1.0" encoding="UTF-8"?>
<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-latest.xsd">

    <changeSet id="2026-003-create-blog-image" author="test">
        <sql>
            CREATE TABLE `blog_image` (
                `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
                `account` VARCHAR(64) NOT NULL COMMENT '上传者账号',
                `original_name` VARCHAR(255) DEFAULT NULL COMMENT '原始文件名',
                `file_name` VARCHAR(255) NOT NULL COMMENT '存储文件名',
                `file_path` VARCHAR(500) NOT NULL COMMENT '文件存储路径',
                `image_url` VARCHAR(500) NOT NULL COMMENT '图片访问URL',
                `file_size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)',
                `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
                PRIMARY KEY (`id`),
                KEY `idx_account` (`account`),
                KEY `idx_create_time` (`create_time`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图片上传记录表';
        </sql>
    </changeSet>

</databaseChangeLog>

这里有几个关键点:

  • id 用来标识这次变更;
  • author 表示变更作者;
  • <sql> 中是真正要执行的数据库脚本;
  • id + author + 文件路径 共同决定一个 changeSet 的唯一性。

也就是说,这段 SQL 不再是一段临时脚本,而是一个受 Liquibase 管理的数据库变更单元。

五、使用 Liquibase 的注意事项

Liquibase 好用,但不能乱用。下面这些点非常关键。

1. 已执行过的 changeSet 不要随便改

这是最常见的坑。如果某个 changeSet 已经在测试或生产环境执行过,后面又修改了它的 SQL,Liquibase 会发现 checksum 不一致。

正确做法一般是:

  • 已执行过的 changeSet 尽量保持不变;
  • 后续调整通过新的 changeSet 完成;
  • 把 changelog 当作数据库历史,而不是普通草稿文件。

2. id 命名要有规范

建议使用有含义的 id,比如:

2026-003-create-blog-image
2026-004-add-blog-image-index
2026-005-update-blog-status

不要简单写成:

001
002
003

项目小的时候没问题,项目大了以后很难维护。

3. SQL 要经过 Review

Liquibase 能保证流程可控,但不能保证 SQL 本身一定安全。比如这些操作仍然需要谨慎:

  • 大表加字段;
  • 大表建索引;
  • 修改字段类型;
  • 删除字段;
  • 删除表;
  • 大批量 update;
  • 涉及数据迁移的脚本。

尤其是生产环境,大表 DDL 可能带来锁表、慢查询、主从延迟等问题。Liquibase 不是数据库性能风险的免死金牌。

4. 不要轻易删除历史 changelog

历史 changelog 文件不是执行完就没用了。它们是数据库从零演进到当前状态的完整路径。如果随便删除,可能会导致新环境初始化失败,也会影响问题追踪。

5. 回滚要单独设计,不要盲目信任自动回滚

Liquibase 支持 rollback,但生产环境的回滚不能只看结构。比如:

  • 加字段可以 drop 掉;
  • 建索引可以 drop 掉;
  • 但删除字段后的数据可能已经丢了;
  • 数据更新后也未必能完整恢复。

所以高风险变更要提前设计回滚方案,必要时先备份数据。

6. 不同环境要统一入口

不要一部分环境用 Liquibase,一部分环境手动 SQL。这样很快就会重新回到环境不一致的问题。

更推荐的方式是:

  • 本地可以手动触发;
  • 测试环境自动执行;
  • 预发环境走发布流程;
  • 生产环境通过受控流水线执行。

重点是:所有环境最终都应该以 changelog 为准。

六、Liquibase 适合什么场景?

我认为 Liquibase 特别适合这些项目:

  • 多人协作开发;
  • 有测试、预发、生产多个环境;
  • 发布比较频繁;
  • 数据库结构经常变;
  • 希望减少人工操作生产库;
  • 希望数据库变更能被 Review 和追踪;
  • 希望新环境可以自动初始化。

如果是非常小的 Demo 项目,可能直接执行 SQL 更快。但只要项目开始长期维护,有多人协作和正式上线流程,Liquibase 的价值就会越来越明显。

七、总结

Liquibase 不是为了让数据库变更变复杂。恰恰相反,它是为了让数据库变更变得更可靠。它把原本分散、临时、依赖人工执行的 SQL,变成了有编号、有作者、有记录、有顺序、有校验的变更过程。

用 Liquibase 之后,数据库变更不再是:"我连上生产库执行一下。" 而是:"我提交一个受控的 changeSet,经过 Review,在发布流程中执行,并留下完整记录。" 这才是它真正的价值。

总结一下,Liquibase 带来的优势主要是:

  • 数据库变更可控;
  • 执行过程可追溯;
  • 环境结构更一致;
  • 减少直接操作线上数据库;
  • 方便接入 CI/CD;
  • 新环境初始化更简单;
  • 历史变更更容易审计。

当然,Liquibase 只是工具,不是万能保险。SQL 是否安全、变更方案是否合理、生产执行时机是否合适,仍然需要团队认真评估。但从工程化角度看,Liquibase 确实能让数据库变更从"手工活"变成"标准流程"。这也是它最值得引入的地方。




上一篇:Shopify 2026全员AI化:Token无上限、自研三工具与AI编码真实瓶颈
下一篇:x402 协议灰色地带:未经授权的 API 套壳如何侵蚀代理经济?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-29 09:06 , Processed in 1.058098 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表