当我在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)

可能是达到了同时会话/事务的数量吗?有人有什么想法吗?


当前回答

有时截断或删除DATABASECHANGELOGLOCK表不起作用。我使用PostgreSQL数据库,遇到过这个问题很多次。我所做的解决方案是回滚在后台为该数据库运行的准备语句。尝试回滚所有准备好的语句,并再次尝试liqubase更改。

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

如果上面的语句返回任何记录,那么用下面的SQL语句回滚准备好的语句。

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';

其他回答

您可以手动或使用query安全地删除表。它将被自动重新创建。

DROP TABLE DATABASECHANGELOGLOCK;

问题是在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或删除该表并重新创建。

在postgres 12中,我需要使用这个命令:

UPDATE DATABASECHANGELOGLOCK SET LOCKED=false, LOCKGRANTED=null, LOCKEDBY=null where ID=1;

有时,如果更新应用程序突然停止,那么锁仍然卡住。

然后运行

UPDATE DATABASECHANGELOGLOCK SET LOCKED=0, LOCKGRANTED=null, LOCKEDBY=null where ID=1;

对数据库有帮助。

你可能还需要将LOCKED=0替换为LOCKED=FALSE。

或者您可以简单地删除DATABASECHANGELOGLOCK表,它将被重新创建。

这里没有提到使用哪个环境来执行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,请修改。