web-dev-qa-db-ja.com

リキベースロック - その理由

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)

同時セッション数/トランザクション数に達したのでしょうか。誰かアイデアがありますか?

198
Peter Isberg

更新アプリケーションが突然停止された場合、ロックが動かなくなることがあります。

それから走っている

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

データベースに対して役立ちます。

あるいはDATABASECHANGELOGLOCKテーブルを削除するだけで、再作成されます。

450
Adrian Ber

おそらくDATABASECHANGELOGLOCKテーブルのロックを解除していない、killされたliquibaseプロセスが原因です。その後、

DELETE FROM DATABASECHANGELOGLOCK;

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

編集: @Adrian Berの答えはこれより良い解決策を提供します。あなたが彼の解決をしている問題があるならば、これをするだけです。

48
e18r

問題は、LiquibaseのSequenceExistsのバグのある実装でした。これらのステートメントによるチェンジセットは非常に長い時間がかかり、誤って中止されたため。それから、次にロックをかけたリキベーススクリプトを実行します。

  <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に変更するか、そのテーブルを削除して再作成するだけです。

22
Peter Isberg

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

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

上記の文でレコードが返された場合は、その準備された文を次のSQL文でロールバックします。

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';
3
CodingFreak

どの環境がLiquibaseの実行に使用されるかについては言及されていません。 Spring Boot 2の場合、直接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();
    }
}

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

このクラスはliquibase.extパッケージに配置する必要があり、Spring Boot 2の自動設定によって選択されます。

1
k_o_

これはOPの問題ではなかったことを私は理解していますが、私は最近別の原因でこの問題に遭遇しました。参考のために、私はSQL ServerでLiquibase Mavenプラグイン(liquibase-maven-plugin:3.1.1)を使用していました。

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

私は知っていますが、かなりの男子生徒の誤りがありますが、誰かが同じ問題に遭遇した場合に備えて、ここでそれを上げています!

0
DarthPablo