Liquibaseロック-理由?


262

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。たぶん、あなたは同時に異なるPCからliquibaseを実行しましたか?他のPCの説明はありませんか?
Jens

ログを編集したところ、誤ってそれをSomeComputerに変更するのを忘れました
Peter

チェンジセットを同時に実行していますか?私は、各ファイルとその中の各チェンジセットが1つずつ実行されると考えました。少なくとも私はそれをこのように使っています。他のすべてを含む1つのマスターチェンジセットファイルがあり、すべてが1つずつ実行されます。
Jens

回答:


572

更新アプリケーションが突然停止した場合、ロックがスタックしたままになることがあります。

その後、実行

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

1
私はFALSEfor を切り替える必要がありましたb'0'
OrangePot

2
これは正しい解決策です。役に立たないため、テーブルを空にしないでください。ドロップするか、LOCKEDフラグを「FALSE」に更新します
Aditya T

55

2020年6月の編集

このアドバイスに従わないでください。それは長年にわたって多くの人々にトラブルを引き起こしています。それはずっと前に私のために働き、私はそれを誠実に投稿しましたが、明らかにそれを行う方法ではありません。DATABASECHANGELOCKテーブルにはデータを含める必要があるため、テーブルからすべてを削除することはお勧めできません。

たとえば、Leos Literakはこれらの指示に従い、サーバーは起動に失敗しました。

元の答え

強制終了したliquibaseプロセスがDATABASECHANGELOGLOCKテーブルのロックを解放していないことが原因である可能性があります。そして、

DELETE FROM DATABASECHANGELOGLOCK;

あなたを助けるかもしれません。

編集: @Adrian Berの答えはこれよりも良い解決策を提供します。これを行うのは、彼の解決策の実行に問題がある場合のみです。


1
これは質問に対する答えを提供しません。批評したり、著者に説明を求めるには、投稿の下にコメントを残してください。
Rachcha、2015年

@Rachcha私はそれをよりよく説明しました。このようにあなたがそれをもっと好きになることを願っています。
e18r

12
上記のアドバイスに従わないでください。DATABASECHANGELOGLOCKには、例外が発生する行がない行が含まれている必要があります
odedsh

これは役に立ちません。テーブルを削除するか、ロック状態を「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>

LockdataはテーブルDATABASECHANGELOCKに格納されます。ロックを取り除くには、1を0に変更するか、そのテーブルを削除して再作成します。


1
liquibase 3.0.2(私が使用しているバージョン)では、1行をロックテーブルから削除しないでください。削除すると、liquibaseが1つの行(またはテーブル全体が欠落しています)。ピーターが言ったように、その情報を追加したかっただけです。古いバージョンでは、行も削除するように機能したようです。
Kariem 2013

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();
    }
}

コードはロックの解放を強制しています。これは、エラーが発生した場合やデバッグが中止された場合にリリース呼び出しが呼び出されない可能性があるテスト設定で役立ちます。

クラスはliquibase.extパッケージ内に配置する必要があり、Spring Boot 2自動構成によってピックアップされます。


ソリューションの詳細な説明を提供していただけますか?Spring Boot 2とliquibaseを使用しており、毎回手動でdbのロック状態を削除したくありません。しかし、どのようにForceReleaseLockServiceをリキベースに注入するのか理解できませんでした。このクラスにService / Componentアノテーションを付ける必要はありません。SpringがそれをプライマリBeanとして選択することですか?
Andrej Tihonov

1
それは最後の文で述べられています:「クラスはliquibase.extパッケージに配置する必要があり、Spring Boot 2自動構成によってピックアップされます。」
k_o_

どのようにクラスをに配置しますliquibase.extか?プロジェクトでそのパッケージを定義する必要がありますか?
akuma8

プロジェクトでそのパッケージを定義しましたが、動作するようですが、確認できません。@PostConstructログメッセージを使用してメソッドを定義しましたが、出力が表示されません。
akuma8

@ akuma8:はい、その名前でプロジェクトにパッケージを作成します。@PostConstructメソッドはどこで定義しましたか?ForceReleaseLockServiceで?これはSpringサービスではないため、呼び出されません。
k_o_

3

テーブルDATABASECHANGELOGLOCKの切り捨てまたは削除が機能しない場合があります。私はPostgreSQLデータベースを使用していて、この問題に何度も遭遇しました。私が解決することは、そのデータベースのバックグラウンドで実行されている準備済みステートメントをロールバックすることです。準備されたすべてのステートメントをロールバックして、リキベースの変更を再試行してください。

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)を使用していました。

とにかく、データベースを切り替えるスクリプトの1つに誤ってSQL Serverの "use"ステートメントをコピーして貼り付けたため、liquibaseがを実行してを更新DATABASECHANGELOGLOCKし、正しいデータベースでロックを取得しましたが、データベースを切り替えて変更を適用しました。正しいデータベースで変更やリキベースの監査を確認できなかっただけでなく、もちろん、リキベースを再度実行したときに、ロックを取得できませんでした。ロックが「間違った」データベースで解放されたためです。 「正しい」データベースでまだロックされています。ロックを解除する前にliquibaseがロックがまだ適用されていることを確認することを期待していましたが、それはliquibaseのバグ(まだ確認していません)かもしれませんが、それ以降のバージョンでは対処できる可能性があります!とはいえ、機能と見なすことができると思います!

かなりの男子生徒のエラーですが、同じ問題が発生した場合に備えて、ここで発生させます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.