当我在oracle服务器上运行大量的liquibase脚本时,我就遇到了这种情况。电脑就是我。
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Waiting for changelog lock....
Liquibase Update Failed: Could not acquire change log lock. Currently locked by SomeComputer (192.168.15.X) since 2013-03-20 13:39
SEVERE 2013-03-20 16:59:liquibase: Could not acquire change log lock. Currently locked by SomeComputer (192.168.15.X) since 2013-03-20 13:39
liquibase.exception.LockException: Could not acquire change log lock. Currently locked by SomeComputer (192.168.15.X) since 2013-03-20 13:39
at liquibase.lockservice.LockService.waitForLock(LockService.java:81)
at liquibase.Liquibase.tag(Liquibase.java:507)
at liquibase.integration.commandline.Main.doMigration(Main.java:643)
at liquibase.integration.commandline.Main.main(Main.java:116)
可能是达到了同时会话/事务的数量吗?有人有什么想法吗?
问题是在Liquibase中执行SequenceExists有bug。因为包含这些语句的变更集花费了很长时间,并且意外地中止了。然后,下一次尝试执行liquibase脚本时,锁被持有。
<changeSet author="user" id="123">
<preConditions onFail="CONTINUE">
<not><sequenceExists sequenceName="SEQUENCE_NAME_SEQ" /></not>
</preConditions>
<createSequence sequenceName="SEQUENCE_NAME_SEQ"/>
</changeSet>
一个解决方法是使用纯SQL来检查这个:
<changeSet author="user" id="123">
<preConditions onFail="CONTINUE">
<sqlCheck expectedResult="0">
select count(*) from user_sequences where sequence_name = 'SEQUENCE_NAME_SEQ';
</sqlCheck>
</preConditions>
<createSequence sequenceName="SEQUENCE_NAME_SEQ"/>
</changeSet>
Lockdata存储在DATABASECHANGELOCK表中。要摆脱锁,只需将1更改为0或删除该表并重新创建。
我知道这不是OP的问题,但我最近遇到了这个问题,原因不同。作为参考,我在SQL Server上使用了Liquibase Maven插件(Liquibase - Maven -plugin:3.1.1)。
Anyway, I'd erroneously copied and pasted a SQL Server "use" statement into one of my scripts that switches databases, so liquibase was running and updating the DATABASECHANGELOGLOCK, acquiring the lock in the correct database, but then switching databases to apply the changes. Not only could I NOT see my changes or liquibase audit in the correct database, but of course, when I ran liquibase again, it couldn't acquire the lock, as the lock had been released in the "wrong" database, and so was still locked in the "correct" database. I'd have expected liquibase to check the lock was still applied before releasing it, and maybe that is a bug in liquibase (I haven't checked yet), but it may well be addressed in later versions! That said, I suppose it could be considered a feature!
我知道,这是一个学生的错误,但我在这里提出这个问题,以防有人遇到同样的问题!
2020年6月编辑
不要听从这个建议。多年来,它给许多人带来了麻烦。很久以前它就为我工作了,我真诚地发布了它,但显然不是这样做的方式。DATABASECHANGELOCK表中需要有内容,因此只删除其中的所有内容而不删除表是一个坏主意。
例如,Leos Literak执行了这些指令,但服务器无法启动。
原来的答案
这可能是由于一个被杀死的liqubase进程没有释放它在DATABASECHANGELOGLOCK表上的锁。然后,
DELETE FROM DATABASECHANGELOGLOCK;
也许能帮到你。
编辑:@Adrian Ber的回答提供了一个比这更好的解决方案。只有当你在解他的解时有问题时才这么做。
这里没有提到使用哪个环境来执行Liquibase。在Spring Boot 2的情况下,可以扩展liqubase .lockservice. standardlockservice,而不需要直接运行SQL语句,这样更简洁。例如:
/**
* This class is enforcing to release the lock from the database.
*
*/
public class ForceReleaseLockService extends StandardLockService {
@Override
public int getPriority() {
return super.getPriority()+1;
}
@Override
public void waitForLock() throws LockException {
try {
super.forceReleaseLock();
} catch (DatabaseException e) {
throw new LockException("Could not enforce getting the lock.", e);
}
super.waitForLock();
}
}
代码正在强制释放锁。这在测试设置中很有用,在测试设置中,如果出现错误或调试中止,可能不会调用发布调用。
该类必须放在液体中。将被Spring Boot 2自动配置拾取。
Liquibase 4
注意,在Liquibase 4中扩展加载机制已经改变。
现在必须在META-INF/services下创建一个具有实现的完整接口包名称的文件,并且在该文件中必须列出所有扩展名。
这可能意味着在META-INF/services/liquibase.lockservice.LockService中
必须添加这一行:
com.company.liquibase.impl.ForceReleaseLockService
我还没有试过,还在用Liquibase 3,请修改。