database Liquibase 锁 - 原因?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/15528795/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Liquibase lock - reasons?
提问by Peter Isberg
I get this when running a lot of liquibase-scripts against a Oracle-server. SomeComputer is me.
在针对 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)
Could it be that the number of simultaneous sessions/transactions are reached? Anyone has any ideas?
是否达到了同时会话/交易的数量?任何人有任何想法?
回答by Adrian Ber
Sometimes if the update application is abruptly stopped, then the lock remains stuck.
有时,如果更新应用程序突然停止,那么锁仍然卡住。
Then running
然后运行
UPDATE DATABASECHANGELOGLOCK SET LOCKED=0, LOCKGRANTED=null, LOCKEDBY=null where ID=1;
against the database helps.
对数据库有帮助。
Or you can simply drop the DATABASECHANGELOGLOCKtable, it will be recreated.
或者您可以简单地删除该DATABASECHANGELOGLOCK表,它将被重新创建。
回答by e18r
It's possibly due to a killed liquibase process not releasing its lock on the DATABASECHANGELOGLOCK table. Then,
这可能是由于一个被杀死的 liquibase 进程没有释放它在 DATABASECHANGELOGLOCK 表上的锁。然后,
DELETE FROM DATABASECHANGELOGLOCK;
might help you.
可能会帮助你。
Edit:@Adrian Ber's answer provides a better solution than this. Only do this if you have any problems doing his solution.
编辑:@Adrian Ber 的回答提供了比这更好的解决方案。仅当您在执行他的解决方案时遇到任何问题时才这样做。
回答by Peter Isberg
The problem was the buggy implementation of SequenceExists in Liquibase. Since the changesets with these statements took a very long time and was accidently aborted. Then the next try executing the liquibase-scripts the lock was held.
问题在于 Liquibase 中 SequenceExists 的错误实现。由于带有这些语句的变更集花费了很长时间并且意外中止。然后下一次尝试执行锁被持有的 liquibase 脚本。
  <changeSet author="user" id="123">
    <preConditions onFail="CONTINUE">
      <not><sequenceExists sequenceName="SEQUENCE_NAME_SEQ" /></not>
    </preConditions>
    <createSequence sequenceName="SEQUENCE_NAME_SEQ"/>
  </changeSet>
A work around is using plain SQL to check this instead:
一种解决方法是使用普通 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 is stored in the table DATABASECHANGELOCK. To get rid of the lock you just change 1 to 0 or drop that table and recreate.
Lockdata 存储在表 DATABASECHANGELOCK 中。要摆脱锁定,您只需将 1 更改为 0 或删除该表并重新创建。
回答by k_o_
It is not mentioned which environment is used for executing Liquibase. In case it is Spring Boot 2 it is possible to extend liquibase.lockservice.StandardLockServicewithout the need to run direct SQL statements which is much cleaner. E.g.:
没有提到使用哪个环境来执行 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();
    }
}
The code is enforcing the release of the lock. This can be useful in test set-ups where the release call might not get called in case of errors or when the debugging is aborted.
代码强制释放锁。这在测试设置中很有用,在这种情况下,在出现错误或调试中止时可能不会调用发布调用。
The class must be placed in the liquibase.extpackage and will be picked up by the Spring Boot 2 auto configuration.
该类必须放在liquibase.ext包中,并且会被 Spring Boot 2 自动配置选取。
回答by Koushik Ravulapelli
Sometimes truncating or dropping the table DATABASECHANGELOGLOCK doesn't work. I use PostgreSQL database and came across this issue a lot of times. What I do for solving is to rollback the prepared statements running in background for that database. Try to rollback all the prepared statements and try the liquibase changes again.
有时截断或删除表 DATABASECHANGELOGLOCK 不起作用。我使用 PostgreSQL 数据库并多次遇到这个问题。我为解决问题所做的是回滚在后台为该数据库运行的准备好的语句。尝试回滚所有准备好的语句并再次尝试 liquibase 更改。
SQL:
查询语句:
SELECT gid FROM pg_prepared_xacts WHERE database='database_name';
If above statement returns any record, then rollback that prepared statement with following SQL statement.
如果上述语句返回任何记录,则使用以下 SQL 语句回滚该准备好的语句。
ROLLBACK PREPARED 'gid_obtained_from_above_SQL';
回答by Mykhaylo Adamovych
You can safely delete the table manually or using query. It will be recreated automatically.
您可以手动或使用查询安全地删除表。它将自动重新创建。
DROP TABLE DATABASECHANGELOGLOCK;
回答by DarthPablo
I appreciate this wasn't the OP's issue, but I ran into this issue recently with a different cause. For reference, I was using the Liquibase Maven plugin (liquibase-maven-plugin:3.1.1) with SQL Server.
我明白这不是 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!
无论如何,我错误地将 SQL Server“use”语句复制并粘贴到我切换数据库的脚本之一中,因此 liquibase 正在运行并更新DATABASECHANGELOGLOCK,获取正确数据库中的锁,然后切换数据库以应用更改。我不仅无法在正确的数据库中看到我的更改或 liquibase 审计,而且当然,当我再次运行 liquibase 时,它无法获取锁,因为锁已在“错误”的数据库中释放,因此仍然锁定在“正确”的数据库中。我本来希望 liquibase 在发布之前检查锁是否仍然应用,也许这是 liquibase 中的一个错误(我还没有检查过),但很可能在以后的版本中得到解决!也就是说,我想它可以被视为一个功能!
Quite a bit of a schoolboy error, I know, but I raise it here in case anyone runs into the same problem!
我知道这是一个小学生的错误,但我在这里提出它,以防有人遇到同样的问题!

