Liquibase锁 - 原因?

时间:2013-03-20 16:06:16

标签: database oracle liquibase

在针对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)

是否达到了同步会话/交易的数量?有人有什么想法吗?

9 个答案:

答案 0 :(得分:443)

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

然后运行

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

对数据库的帮助。

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

答案 1 :(得分:47)

这可能是由于一个被杀死的liquibase进程未在DATABASECHANGELOGLOCK表上释放其锁定。然后,

DELETE FROM DATABASECHANGELOGLOCK;

可能会帮到你。

编辑: @Adrian Ber的回答提供了比这更好的解决方案。只有在解决问题时才会这样做。

答案 2 :(得分:22)

问题是Liquibase中的SequenceExists的错误实现。由于这些陈述的变更集需要很长时间,并且意外中止。然后下一次尝试执行liquibase-scripts锁定。

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

答案 3 :(得分:2)

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

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

如果above语句返回任何记录,则使用以下SQL语句回滚该预准备语句。

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';

答案 4 :(得分:2)

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

DROP TABLE DATABASECHANGELOGLOCK;

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

我很欣赏这不是OP的问题,但最近我遇到了另一个问题。作为参考,我使用了Liquibase Maven插件(liquibase-maven-plugin:3.1.1)和SQL Server。

无论如何,我错误地复制并粘贴了一个SQL Server&#34;使用&#34;在我的一个切换数据库的脚本中的语句,因此liquibase正在运行并更新DATABASECHANGELOGLOCK,获取正确数据库中的锁,但随后切换数据库以应用更改。我不仅无法在正确的数据库中看到我的更改或liquibase审核,当然,当我再次运行liquibase时,它无法获取锁定,因为锁定已在&#34;错误&#中释放34;数据库,所以仍然锁定在&#34;正确&#34;数据库。我预计liquibase会在发布之前检查锁是否仍然应用,也许这是liquibase中的一个错误(我还没有检查过),但它可能会在以后的版本中得到解决!那就是说,我想它可以被认为是一个功能!

我知道,这是一个小学生的错误,但是如果有人遇到同样的问题,我会在这里提出错误!

答案 7 :(得分:0)

没有提到哪个环境用于执行Liquibase。如果是Spring Boot 2,则可以扩展checkNeighbours而不需要运行直接的SQL语句,这更加干净。例如:

liquibase.lockservice.StandardLockService

该代码正在强制释放锁。这在测试设置中很有用,因为在测试设置中,如果发生错误或调试中止,可能不会调用发布调用。

该类必须放在/** * 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自动配置获取。

答案 8 :(得分:0)

请让 Liquibase 处理自己的表。正如 user1434769 所提到的,正确的做法是使用 Liquibase 的 releaseLocks 命令。

使用 Gradle 时,这将是:gradlew releaseLocks