多应用同时执行同一Liquibase脚本可行性及校验失败问题求助
同一数据库下多应用并发执行Liquibase脚本的问题解决
核心问题解答
同一数据库下,不同应用完全可以同时执行同一Liquibase脚本,但必须配置Liquibase的并发安全机制,否则会因变更日志表的竞争访问触发校验和冲突异常。
异常原因解析
你遇到的ValidationFailedException本质是并发竞争问题:两个应用实例同时操作Liquibase的databasechangelog表时,第一个实例正在执行变更集并更新日志记录,第二个实例读取到的日志状态不完整,导致计算出的变更集校验和与已记录值不一致,触发校验失败。
具体解决方案
1. 确保Liquibase数据库锁机制生效
Liquibase默认自带数据库级别的锁(通过databasechangeloglock表),确保同一时间只有一个实例能执行变更脚本,从根源避免并发冲突:
- 检查配置中未禁用锁:确保没有设置
liquibase.locking.enabled=false - 若
databasechangeloglock表不存在,手动创建(Liquibase通常会自动生成,但若之前异常中断可能未创建):CREATE TABLE databasechangeloglock ( ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR(255), PRIMARY KEY (ID) ); INSERT INTO databasechangeloglock (ID, LOCKED) VALUES (1, FALSE);
2. 调整校验和验证策略
如果锁机制仍有问题,可针对冲突的变更集调整校验和规则:
- 在冲突的变更集上添加
validCheckSum属性,允许当前的校验和值:<changeSet id="31-10-2022-IGE-6388" author=".....@.......com" validCheckSum="7:27d219f2f30604542a4a458c891cdbc7"> <!-- 原变更集内容 --> </changeSet> - 注意:全局禁用校验和验证(
liquibase.validateOnMigrate=false)是下策,会失去对变更脚本完整性的校验能力,不推荐使用。
3. 保证共享脚本的一致性
确保两个应用引用的Liquibase脚本完全一致:
- 确认共享代码库的脚本在两个应用中都是同一版本,无本地修改
- 使用固定版本的依赖引用共享代码库,避免动态拉取不同版本的脚本
4. 临时方案:错开启动时间
如果以上配置暂时无法调整,可给其中一个应用添加启动延迟,手动错开Liquibase的执行时间:
- 在启动脚本中加入延迟命令,例如:
sleep 30 && java -jar your-application.jar
内容的提问来源于stack exchange,提问作者Praveen kumar
相关产品推荐
相关产品推荐

