Подтвердить что ты не робот

Блокировка Liquibase - причины?

Я получаю это при запуске большого количества скриптов Liquibase против Oracle-сервера. 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)

Может ли быть достигнуто количество одновременных сеансов/транзакций? У кого-нибудь есть идеи?

4b9b3361

Ответ 1

Иногда, если приложение обновления резко останавливается, блокировка остается застрявшей.

Затем запустите

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

против базы данных помогает.

Или вы можете просто отбросить таблицу DATABASECHANGELOGLOCK, она будет воссоздана.

Ответ 2

Возможно, это связано с тем, что убитый процесс ликбазы не освобождает его замок на таблице DATABASECHANGELOGLOCK. Тогда,

DELETE FROM DATABASECHANGELOGLOCK;

может помочь вам.

Изменить: Ответ @Adrian Ber обеспечивает лучшее решение, чем это. Только делайте это, если у вас возникнут проблемы с его решением.

Ответ 3

Проблема заключалась в ошибочной реализации SequenceExists в Liquibase. Поскольку изменения с этими утверждениями заняли очень много времени и были случайно прерваны. Затем, следующая попытка выполнить скрипты Liquibase, замок был сохранен.

  <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 или бросаете эту таблицу и воссоздаете.

Ответ 4

Иногда усечение или отбрасывание таблицы DATABASECHANGELOGLOCK не работает. Я использую базу данных PostgreSQL и часто сталкивался с этой проблемой. То, что я делаю для решения, - это откат подготовленных операторов, работающих в фоновом режиме для этой базы данных. Попытайтесь отменить все подготовленные заявления и повторите изменения Liquibase.

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

Если вышеприведенный оператор возвращает любую запись, тогда откат, который подготовил оператор с помощью следующего оператора SQL.

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';

Ответ 5

Я понимаю, что это не проблема OP, но я столкнулся с этой проблемой недавно с другой причиной. Для справки я использовал плагин Liquibase Maven (linibase-maven-plugin: 3.1.1) с SQL Server.

Во всяком случае, я ошибочно скопировал и вставил инструкцию SQL Server "use" в один из моих сценариев, который переключает базы данных, так что Liquibase запускает и обновляет DATABASECHANGELOGLOCK, приобретая блокировку в правильной базе данных, но затем переключая базы данных для применения изменений. Я не только не мог видеть мои изменения или ревизию Liquibase в правильной базе данных, но, конечно, когда я снова запускал Liquibase, он не мог получить блокировку, поскольку блокировка была выпущена в "неправильной" базе данных, и так было все еще заблокирован в "правильной" базе данных. Я бы ожидал, что Liquibase проверит, что блокировка все еще применяется, прежде чем выпустить ее, и, возможно, это ошибка в Liquibase (я еще не проверял), но ее можно решить в более поздних версиях! Тем не менее, я полагаю, это можно считать особенностью!

Довольно немного школьной ошибки, я знаю, но я поднимаю ее здесь, если кто-то столкнется с той же проблемой!

Ответ 6

Не упоминается, какая среда используется для выполнения 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.