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


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 2016 년

다른 PC가있는 것 같습니다 : Konsultpc74. 어쩌면 당신은 동시에 다른 PC에서 liquibase를 실행 했습니까? 그렇지 않은 경우 다른 PC에 대한 설명이 있습니까?
Jens

로그를 편집했는데 실수로 로그를 SomeComputer로 변경하는 것을 잊었습니다.
Peter Isberg

변경 세트를 동시에 실행하고 있습니까? 각 파일과 각 변경 세트가 하나씩 실행된다고 생각했습니다. 적어도 나는 이런 식으로 사용합니다. 다른 모든 것을 포함하고 모든 것이 하나씩 실행되는 하나의 마스터 변경 세트 파일이 있습니다.
Jens

답변:


572

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

그런 다음 실행

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

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

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


24
0for 를 전환해야 FALSE했지만 그 외에는 정상적으로 작동했습니다. 감사합니다
mattalxndr

7
@Adrian Ber가 응답 한 것을 실행하는 releaseLocks라는 기본 제공 명령이 Liquibase에 있지만 데이터베이스와 무관하다고 생각합니다.

1
개발 환경 에서이 오류가 발생했습니다. DATABASECHANGELOGLOCK 테이블을 수정하여 해결했습니다.
Naymesh Mistry

1
FALSE대한 전환이 필요했습니다b'0'
OrangePot

2
이것은 올바른 해결책이므로 도움이되지 않으므로 테이블을 비우지 마십시오. 삭제하거나 LOCKED 플래그를 'FALSE'로 업데이트하십시오
Aditya T

55

2020 년 6 월 편집

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

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

원래 답변

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

DELETE FROM DATABASECHANGELOGLOCK;

당신을 도울 수 있습니다.

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


1
이것은 질문에 대한 답변을 제공하지 않습니다. 저자에게 비평을하거나 설명을 요청하려면 게시물 아래에 의견을 남겨주십시오.
Rachcha

@ Rachacha 나는 그것을 더 잘 설명했다. 당신이 이것처럼 더 좋아 바랍니다.
e18r

12
위의 조언을 따르지 마십시오. DATABASECHANGELOGLOCK는 예외 얻을 것이다 모든 행없이 행을 포함해야한다
odedsh

이것은 도움이되지 않습니다. 테이블을 삭제하거나 잠긴 상태를 'false'로 업데이트하는 대신 시도했습니다. 효과가 없었습니다.
Aditya T

이 답변을 따르면 미래의 스크립트가 잠금이 존재하기 때문에 실행되지 않을 가능성이 높습니다. 이 작업을 완료 한 경우 이미이 문제를 해결하기 위해 빈 잠금 장치를 추가 할 수 있습니다 INSERT INTO yourdb.DATABASECHANGELOGLOCK VALUES (1, 0, null, null);
루디 커 쇼우

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>

잠금 데이터는 DATABASECHANGELOCK 테이블에 저장됩니다. 잠금을 제거하려면 1을 0으로 변경하거나 해당 테이블을 삭제하고 다시 작성하십시오.


1
liquibase 3.0.2 (사용중인 버전)에서 잠금 테이블에서 한 줄을 제거하지 마십시오. liquibase는 한 행이있을 것으로 예상하므로 다음에 liquibase를 실행할 때 다른 오류가 발생합니다. 전체 테이블 누락). Peter가 말했듯이 이전 버전에서는 행을 제거하는 데 효과가 있었기 때문에 해당 정보를 추가하려고했습니다.
Kariem

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를 liquibase에 주입하는 방법을 이해하지 못했습니다. 이 클래스에 서비스 / 컴포넌트 주석을 넣을 필요가 없다. 스프링이이를 기본 빈으로 선택 하는가?
Andrej Tihonov

1
마지막 문장에 언급되어있다 : "클래스는 liquibase.ext 패키지에 위치해야하며 Spring Boot 2 자동 구성에 의해 선택 될 것입니다."
k_o_

에 클래스를 어떻게 배치 liquibase.ext합니까? 프로젝트에서 해당 패키지를 정의해야합니까?
akuma8

프로젝트에서 패키지를 정의했는데 작동하는 것 같지만 확인할 수 없습니다. @PostConstruct로그 메시지 로 메소드를 정의 했지만 인쇄되지 않습니다.
akuma8

@ akuma8 : 예, 프로젝트에 해당 이름으로 패키지를 만드십시오. 방법을 어디에서 정의 했 @PostConstruct습니까? ForceReleaseLockService에서? 이것은 스프링 서비스가 아니므로 호출되지 않습니다.
k_o_

3

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

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)을 사용하고있었습니다.

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

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.