[database] Liquibase Lock-이유는 무엇입니까?

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)

동시 세션 / 트랜잭션 수에 도달했을 수 있습니까? 누구든지 아이디어가 있습니까?



답변

때로는 업데이트 응용 프로그램이 갑자기 중지 된 경우 잠금이 계속 유지됩니다.

그런 다음 실행

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

데이터베이스 도움이됩니다.

또는 단순히 DATABASECHANGELOGLOCK테이블을 삭제하면 다시 작성됩니다.


답변

2020 년 6 월 편집

이 조언을 따르지 마십시오. 수년 동안 많은 사람들에게 문제를 일으켰습니다. 그것은 오래 전에 저에게 효과가 있었고 선의로 게시했지만 분명히 그렇게 할 수는 없습니다. DATABASECHANGELOCK 테이블에 내용이 있어야하므로 모든 것을 삭제하는 것은 좋지 않습니다.

예를 들어 Leos Literak은이 지침을 따르고 서버를 시작하지 못했습니다.

원래 답변

DATABASECHANGELOGLOCK 테이블에서 잠금을 해제하지 않은 종료 된 liquibase 프로세스 때문일 수 있습니다. 그때,

DELETE FROM DATABASECHANGELOGLOCK;

당신을 도울 수 있습니다.

편집 : @Adrian Ber의 대답은 이것보다 더 나은 해결책을 제공합니다. 그의 솔루션을 수행하는 데 문제가있는 경우에만이를 수행하십시오.


답변

문제는 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으로 변경하거나 해당 테이블을 삭제하고 다시 작성하십시오.


답변

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 자동 구성에 의해 선택됩니다.


답변

때때로 DATABASECHANGELOGLOCK 테이블이 잘 리거나 삭제되지 않습니다. PostgreSQL 데이터베이스를 사용 하고이 문제를 여러 번 발견했습니다. 해결을 위해하는 일은 해당 데이터베이스에 대해 백그라운드에서 실행중인 준비된 명령문을 롤백하는 것입니다. 준비된 모든 명령문을 롤백하고 liquibase 변경을 다시 시도하십시오.

SQL :

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

위의 명령문이 레코드를 리턴하면 다음 SQL 문으로 준비된 명령문을 롤백하십시오.

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';


답변

테이블을 수동으로 또는 쿼리를 사용하여 안전하게 삭제할 수 있습니다. 자동으로 다시 생성됩니다.

DROP TABLE DATABASECHANGELOGLOCK;


답변

이것이 OP의 문제는 아니었지만 최근 다른 원인으로이 문제가 발생했습니다. 참고로 SQL Server에서 Liquibase Maven 플러그인 (liquibase-maven-plugin : 3.1.1)을 사용하고있었습니다.

어쨌든, 데이터베이스를 전환하는 스크립트 중 하나에 SQL Server “use”문을 잘못 복사하여 붙여 넣었으므로 liquibase가 실행 중이고 업데이트 DATABASECHANGELOGLOCK하여 올바른 데이터베이스에서 잠금을 획득 한 다음 변경 내용을 적용하기 위해 데이터베이스를 전환했습니다. 올바른 데이터베이스에서 변경 사항 또는 liquibase 감사를 볼 수 없었을뿐만 아니라 liquibase를 다시 실행했을 때 잠금이 “잘못된”데이터베이스에서 해제되었으므로 잠금을 획득 할 수 없었습니다. 여전히 “올바른”데이터베이스에 잠겨 있습니다. 나는 잠금을 풀기 전에 liquibase가 잠금이 여전히 적용되었는지 확인했을 것으로 예상했을 것입니다. 아마도 liquibase의 버그 일 것입니다 (아직 확인하지 않았습니다).하지만 이후 버전에서도 해결 될 수 있습니다! 즉, 기능으로 간주 될 수 있다고 생각합니다!

상당히 남학생의 실수이지만, 같은 문제가 발생하는 경우를 대비하여 여기에 올립니다.