Liquibase如何从SQL变更日志中获取DML操作的影响行数输出
捕获Liquibase中DML操作执行结果的实现方法
Liquibase默认执行变更集时,只会记录变更是否执行成功、执行耗时等通用信息,不会主动输出类似SQL Server Management Studio中“1行受影响”这类DML操作的返回结果,要拿到这类内容可以通过以下几种可落地的方式实现:
1. 变更集内嵌入SQL捕获逻辑,纯脚本实现无代码侵入
这是成本最低的实现方式,不需要开发Java扩展,直接在现有格式化SQL变更集里,跟在DML语句后面追加行数捕获的逻辑即可。
以SQL Server环境适配你给出的变更集为例,改造后的脚本如下:
--liquibase formatted sql --changeset tester:2 INSERT INTO liquibaseTest(id, description) values (3, 'some really cool stuff'); -- 捕获当前会话最近一条DML的受影响行数,写入自建执行日志表 INSERT INTO dml_exec_log(changeset_identifier, affected_row_count, exec_timestamp) VALUES ('tester:2', @@ROWCOUNT, SYSUTCDATETIME());
不同数据库的行数捕获语法有区别,对应替换即可:
- SQL Server:使用全局变量
@@ROWCOUNT获取最近一条语句的受影响行数 - MySQL/MariaDB:使用函数
ROW_COUNT()获取 - PostgreSQL:使用
GET DIAGNOSTICS integer_var = ROW_COUNT;语法捕获
捕获到的行数可以写入自定义日志表,后续直接查询表就能拿到每一个DML操作的实际影响行数。
2. 基于Liquibase扩展点做全局拦截
如果不想在每个变更集里重复写捕获逻辑,可以通过Liquibase提供的监听器扩展接口实现全局能力:
- 实现
ChangeEventListener接口,在ran(变更执行完成后的回调)方法里,判断当前执行的语句是否为insert/update/delete类的DML - 通过当前持有的数据库连接,获取对应语句的执行返回值,提取受影响行数
- 将提取到的行数、关联的变更集ID、执行时间统一输出到项目的日志系统(Logback/Log4j等)中,和常规应用日志一起检索
注意:全局拦截实现时,要过滤掉建表、加索引这类DDL操作,仅针对DML语句做行数捕获,避免不必要的性能损耗。
3. 调整日志级别获取通用执行信息
如果不需要精准的受影响行数,只是希望拿到数据库驱动返回的通用执行状态,可以直接将Liquibase的日志级别调整为DEBUG:
- 在项目的日志配置中,将
liquibase根包的日志等级设置为DEBUG - 该级别下Liquibase会完整输出所有执行的原始SQL语句,部分数据库驱动会在返回执行结果时,直接将受影响行数拼接到日志输出中,不需要额外开发即可看到相关信息
说明:Liquibase核心逻辑中没有提供开箱即用的“输出DML受影响行数”配置项,这是因为它的设计逻辑是只要DML执行没有抛出异常,就判定变更执行成功,不会主动拉取语句执行的行数统计返回值,要拿到类似SSMS的交互式输出,必须通过上述几种主动捕获的方式实现。
内容的提问来源于stack exchange,提问作者flerngobot
相关产品推荐
相关产品推荐

