2013-03-20 15 views
137

Ich bekomme das, wenn ich viele liquibase-Skripte gegen einen Oracle-Server laufen lasse. Irgendein Computer bin ich.Liquibase-Sperre - Gründe?

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) 

Könnte es sein, dass die Anzahl gleichzeitiger Sitzungen/Transaktionen erreicht wird? Hat jemand irgendwelche Ideen?

+1

Haben Sie die JVM getötet, während die liquibase die Sperre gehalten hat? Das ist der einzige Fall, in dem das für mich passiert. –

+0

Es scheint ein anderer PC beteiligt zu sein: Konsultpc74. Vielleicht hast du liquibase von verschiedenen PCs gleichzeitig ausgeführt? Wenn nicht, hast du eine Erklärung für den anderen PC? – Jens

+0

Ich habe die Logs bearbeitet und versehentlich vergessen, das zu SomeComputer zu ändern. –

Antwort

18

Das Problem war die fehlerhafte Implementierung von SequenceExists in Liquibase. Da die Änderung mit diesen Anweisungen sehr lange dauerte, wurde sie versehentlich abgebrochen. Dann versuchen Sie das nächste Mal, die liquibase-Skripte auszuführen, die die Sperre enthielt.

<changeSet author="user" id="123"> 
    <preConditions onFail="CONTINUE"> 
     <not><sequenceExists sequenceName="SEQUENCE_NAME_SEQ" /></not> 
    </preConditions> 
    <createSequence sequenceName="SEQUENCE_NAME_SEQ"/> 
    </changeSet> 

A Arbeit um Klar SQL verwendet diese anstatt zu überprüfen:

<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 in der Tabelle DATABASECHANGELOCK gespeichert ist. Um die Sperre loszuwerden, ändern Sie einfach 1 zu 0 oder lassen Sie die Tabelle fallen und erstellen Sie sie neu.

+1

In Liquibase 3.0.2 (die Version, die ich verwende), entfernen Sie nicht die eine Zeile aus der Sperrtabelle, oder Sie werden einen anderen Fehler haben, wenn Sie liquibase das nächste Mal ausführen, weil liquibase erwartet, dass eine Zeile da ist (oder der ganze Tisch fehlt). Genau wie Peter sagte, wollte nur diese Info hinzufügen, denn in älteren Versionen scheint es auch zu funktionieren, die Zeile zu entfernen. – Kariem

310

Wenn die Update-Anwendung abrupt gestoppt wird, bleibt die Sperre manchmal hängen.

Dann

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

gegen die Datenbank hilft läuft.

Oder Sie können einfach die DATABASECHANGELOGLOCK Tabelle fallen lassen, es wird neu erstellt.

+10

Ich musste die "0" für "FALSE" ausschalten, aber ansonsten hat es funktioniert. Danke – mattalxndr

+5

Es gibt einen eingebauten Befehl in Liquibase namens releaseLocks, der ausführen würde, was @Adrian Ber antwortete, aber ich denke, dass es datenbankunabhängig ist. –

+0

Ich habe gerade diesen Fehler in meiner Entwicklungsumgebung bekommen. Das Reparieren des DATABASECHANGELOGLOCK-Tisches löste es. –

0

Ich weiß zu schätzen, dass dies nicht das Problem des OP war, aber ich stieß vor kurzem mit einer anderen Ursache auf dieses Problem. Als Referenz benutzte ich das Liquibase Maven Plugin (liquibase-maven-plugin: 3.1.1) mit SQL Server.

Wie auch immer, ich hatte irrtümlich kopiert und eingefügt eine SQL Server "use" -Anweisung in eines meiner Skripte, die Datenbanken wechselt, so liquibase lief und aktualisiert die DATABASECHANGELOGLOCK, die Sperre in der richtigen Datenbank erwerben, aber dann Datenbanken wechseln um die Änderungen zu übernehmen. Nicht nur konnte ich meine Änderungen oder liquibase in der richtigen Datenbank NICHT sehen, aber natürlich, als ich liquibase wieder lief, konnte es die Sperre nicht erwerben, da die Sperre in der "falschen" Datenbank veröffentlicht worden war und so war immer noch in der "richtigen" Datenbank gesperrt. Ich hätte erwartet, dass liquibase überprüfen würde, ob die Sperre noch angewendet wurde, bevor es veröffentlicht wird, und vielleicht ist das ein Fehler in liquibase (ich habe das noch nicht überprüft), aber es könnte in späteren Versionen angesprochen werden! Das heißt, ich denke, es könnte als ein Merkmal betrachtet werden!

Ziemlich ein Schuljungen Fehler, ich weiß, aber ich hebe es hier für den Fall, dass jemand in das gleiche Problem läuft!

29

Es ist möglicherweise wegen eines getöteten liquibase-Prozesses, der seine Sperre auf der DATABASECHANGELOGLOCK-Tabelle nicht freigibt. Dann,

DELETE FROM DATABASECHANGELOGLOCK; 

könnte Ihnen helfen.

Bearbeiten: @Adrian Ber Antwort bietet eine bessere Lösung als diese. Tun Sie dies nur, wenn Sie Probleme mit seiner Lösung haben.

+1

Dies liefert keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag. – Rachcha

+0

@Rachcha Ich erklärte es besser. Hoffe es gefällt dir eher so. – emisilva

+7

Befolgen Sie nicht die obigen Hinweise. DATABASECHANGELOGLOCK muss Zeilen ohne Zeilen enthalten Sie erhalten eine Ausnahme – odedsh

0

Manchmal Abbrechen oder Löschen der Tabelle DATABASECHANGELOGLOCK funktioniert nicht. Ich benutze PostgreSQL-Datenbank und stieß oft auf dieses Problem. Ich lösche die vorbereiteten Anweisungen, die im Hintergrund für diese Datenbank ausgeführt werden. Versuchen Sie, alle vorbereiteten Anweisungen rückgängig zu machen, und versuchen Sie erneut, Änderungen an der liquibase vorzunehmen.

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name'; 

Wenn obige Aussage jeden Datensatz zurückgibt, Rollback dann die vorbereitete Anweisung mit SQL-Anweisung folgt.

ROLLBACK PREPARED 'gid_obtained_from_above_SQL'; 
Verwandte Themen