Liquibase锁定-原因?


261

当对Oracle服务器运行许多liquibase脚本时,我得到了这个。SomeComputer是我。

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)

是否可以达到同时进行的会话/事务的数量?有人有什么想法吗?


2
您在liquibase锁定时杀死了JVM吗?那是我遇到的唯一情况。
Christoph Leiter

似乎还涉及另一台PC:Konsultpc74。也许您同时将liquibase从不同的PC上运行了?如果没有,您是否对另一台PC有解释?
詹斯

我编辑了日志,却意外地忘记将其更改为SomeComputer
Peter

您是否同时执行变更集?我认为其中的每个文件和每个变更集都是一个接一个地执行的。至少我以这种方式使用它。我有一个主变更集文件,其中包含所有其他文件,并且所有内容都一个一个地运行。
詹斯

Answers:


571

有时,如果更新应用程序突然停止,则该锁将保持卡住状态。

然后跑步

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

对数据库有帮助。

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


24
我需要切换0for FALSE,但是除此之外,它运行良好。谢谢
mattalxndr 2014年

7
Liquibase中有一个称为releaseLocks的内置命令,该命令将执行@Adrian Ber回答的内容,但我认为这与数据库无关。

1
我只是在开发环境中遇到此错误。修复DATABASECHANGELOGLOCK表即可解决该问题。
Naymesh Mistry'7

1
我需要转出FALSEb'0'
OrangePot

2
这是正确的解决方案,请不要尝试清空表,因为这样做无济于事。无论是拖放或更新锁定的标志为“假”
阿迪亚ŧ

55

编辑2020年6月

不要遵循这个建议。这些年来给很多人带来了麻烦。很久以前,它对我有用,我真诚地发布了它,但这显然不是实现它的方法。DATABASECHANGELOCK表需要包含一些东西,因此仅删除表中的所有内容是一个坏主意。

例如,Leos Literak遵循这些指示,服务器无法启动。

原始答案

这可能是由于终止的liquibase进程未释放其对DATABASECHANGELOGLOCK表的锁定。然后,

DELETE FROM DATABASECHANGELOGLOCK;

可能会帮助您。

编辑: @Adrian Ber的答案提供了一个比此更好的解决方案。仅当您在解决他的问题时遇到任何问题时才这样做。


1
这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论。
Rachcha

@Rachcha我更好地解释了。希望你喜欢这样。
e18r

12
不要遵循上述建议。DATABASECHANGELOGLOCK必须包含不包含任何行的行,否则您将获得异常
odedsh 2015年

这无济于事,我尝试了此操作,而不是删除表或将锁定状态更新为“ false”。它没有用。
Aditya T

如果您遵循此答案,那么将来的脚本很有可能不会运行,因为它们希望该锁存在。如果您已完成此操作,则可以添加一个空锁来解决此问题 INSERT INTO yourdb.DATABASECHANGELOGLOCK VALUES (1, 0, null, null);
Rudi Kershaw

24

问题是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>

锁数据存储在表DATABASECHANGELOCK中。要摆脱锁定,只需将1更改为0或删除该表并重新创建即可。


1
在liquibase 3.0.2(我正在使用的版本)中,请勿从锁定表中删除一行,否则,下次运行liquibase时会出现不同的错误,因为liquibase希望一行存在(或整张表丢失)。就像彼得所说的那样,只是想添加该信息,因为在旧版本中,它似乎也可以删除该行。
卡列姆

7

没有提到哪个环境用于执行Liquibase。如果是Spring Boot 2,则可以扩展liquibase.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();
    }
}

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

该类必须放在liquibase.ext包中,并由Spring Boot 2自动配置获取。


您能否提供您的解决方案的详细说明?我们使用Spring Boot 2和liquibase,并且不想每次都手动删除db中的锁定状态。但是我不明白如何将ForceReleaseLockService注入liquibase。我不必在该类上放置Service / Component注释,Spring是否将其选择为主豆?
Andrej Tihonov

1
在最后一句话中提到:“该类必须放在liquibase.ext包中,并且将由Spring Boot 2自动配置获取。”
k_o_

您如何将类放在中liquibase.ext,我是否需要在项目中定义该包?
akuma8

我在我的项目中定义了该程序包,它似乎可以工作,但我无法对其进行验证。我@PostConstruct用日志消息定义了一个方法,但看不到它打印出来。
akuma8

@ akuma8:是的,只需在项目中使用该名称创建一个包。您在哪里定义@PostConstruct方法?在ForceReleaseLockService中?这不是Spring服务,因此不会被调用。
k_o_

3

有时截断或删除表DATABASECHANGELOGLOCK无效。我使用PostgreSQL数据库,并且多次遇到此问题。我要做的是回退在该数据库的后台运行的准备好的语句。尝试回滚所有准备好的语句,然后再次尝试更改liquibase。

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

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

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';

1

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

DROP TABLE DATABASECHANGELOGLOCK;

0

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

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

我知道这有点像男生的错误,但是如果有人遇到同样的问题,我会在这里提出来!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.