321 votes

Blocage de Liquibase - raisons ?

J'ai ce problème lorsque je fais tourner beaucoup de liquibase-scripts contre un serveur Oracle. Je suis 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)

Se pourrait-il que le nombre de sessions/transactions simultanées soit atteint ? Quelqu'un a-t-il une idée ?

3 votes

Avez-vous tué la JVM pendant que liquibase tenait le verrou ? C'est le seul cas où cela se produit pour moi.

0 votes

Il semble qu'un autre PC soit impliqué : Konsultpc74. Peut-être avez-vous lancé liquibase sur deux PC différents en même temps ? Sinon, avez-vous une explication pour l'autre PC ?

0 votes

J'ai édité les logs et j'ai accidentellement oublié de changer cela en SomeComputer.

711voto

Adrian Ber Points 1829

Parfois, si l'application de mise à jour est brusquement arrêtée, le verrou reste bloqué.

Puis en courant

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

contre la base de données aide.

Vous devrez peut-être aussi remplacer LOCKED=0 con LOCKED=FALSE .

Ou vous pouvez simplement laisser tomber le DATABASECHANGELOGLOCK il sera recréé.

40 votes

J'avais besoin de changer le 0 pour FALSE mais à part ça, ça a bien marché. Merci

9 votes

Il existe une commande intégrée dans Liquibase appelée releaseLocks qui exécuterait ce que @Adrian Ber a répondu mais je pense qu'elle est indépendante de la base de données.

1 votes

Je viens d'obtenir cette erreur dans mon environnement de développement. La correction de la table DATABASECHANGELOGLOCK l'a résolu.

67voto

Emi Points 11

Édition juin 2020

Ne suivez pas ce conseil. Il a causé des problèmes à de nombreuses personnes au fil des ans. Cela a fonctionné pour moi il y a longtemps et je l'ai posté en toute bonne foi, mais ce n'est clairement pas la bonne façon de procéder. La table DATABASECHANGELOCK doit contenir des éléments, c'est donc une mauvaise idée de tout supprimer sans abandonner la table.

Leos Literak par exemple, a suivi ces instructions et le serveur n'a pas démarré.

Réponse originale

C'est peut-être dû à un processus liquibase tué qui ne libère pas son verrou sur la table DATABASECHANGELOGLOCK. Alors,

DELETE FROM DATABASECHANGELOGLOCK;

pourrait vous aider.

Editar: La réponse de @Adrian Ber fournit une meilleure solution que celle-ci. Ne faites ceci que si vous avez des difficultés à appliquer sa solution.

27voto

Peter Isberg Points 329

Le problème était l'implémentation boguée de SequenceExists dans Liquibase. Comme les changesets avec ces déclarations prenaient beaucoup de temps, ils étaient accidentellement interrompus. Puis, lors de l'essai suivant d'exécution de liquibase-scripts, le verrou était retenu.

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

Une solution consiste à utiliser le langage SQL simple pour vérifier ce point :

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

Les données de verrouillage sont stockées dans la table DATABASECHANGELOCK. Pour se débarrasser du verrou, il suffit de passer de 1 à 0 ou de supprimer cette table et de la recréer.

1 votes

Dans liquibase 3.0.2 (la version que j'utilise), ne supprimez pas la ligne de la table de verrouillage, ou vous obtiendrez une erreur différente lors de la prochaine exécution de liquibase, car liquibase s'attend à ce que cette ligne soit présente (ou que la table entière soit manquante). Exactement comme Peter l'a dit, je voulais juste ajouter cette information, parce que dans les versions antérieures, il semble avoir fonctionné en supprimant également la ligne.

10voto

user1036 Points 21

Il n'est pas mentionné quel environnement est utilisé pour exécuter Liquibase. S'il s'agit de Spring Boot 2, il est possible d'étendre la fonction liquibase.lockservice.StandardLockService sans avoir besoin d'exécuter des instructions SQL directes, ce qui est beaucoup plus propre. Par exemple :

/**
 * 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();
    }
}

Le code impose la libération de la serrure. Cela peut être utile dans les configurations de test où l'appel de libération peut ne pas être appelé en cas d'erreurs ou lorsque le débogage est interrompu.

La classe doit être placée dans le liquibase.ext et sera récupéré par la configuration automatique de Spring Boot 2.

3voto

DarthPablo Points 66

Je comprends que ce n'était pas le problème de l'OP, mais j'ai rencontré ce problème récemment avec une cause différente. Pour référence, j'utilisais le plugin Maven de Liquibase (liquibase-maven-plugin:3.1.1) avec SQL Server.

Quoi qu'il en soit, j'avais copié et collé par erreur une instruction "use" de SQL Server dans l'un de mes scripts qui change de base de données, de sorte que liquibase était en cours d'exécution et mettait à jour la DATABASECHANGELOGLOCK , en acquérant le verrou dans la bonne base de données, mais en changeant ensuite de base de données pour appliquer les modifications. Non seulement je ne pouvais PAS voir mes modifications ou l'audit de liquibase dans la bonne base de données, mais bien sûr, lorsque j'ai relancé liquibase, il n'a pas pu acquérir le verrou, car le verrou avait été libéré dans la " mauvaise " base de données, et était donc toujours verrouillé dans la " bonne " base de données. Je m'attendais à ce que liquibase vérifie que le verrou était toujours appliqué avant de le libérer, et c'est peut-être un bogue dans liquibase (je n'ai pas encore vérifié), mais il pourrait bien être corrigé dans les versions ultérieures ! Ceci dit, je suppose que cela peut être considéré comme une fonctionnalité !

C'est un peu une erreur d'écolier, je sais, mais je la soulève ici au cas où quelqu'un rencontrerait le même problème !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X