Likibaz kilidi - nedenleri?


262

Bir Oracle sunucusuna karşı çok sayıda liquibase-script çalıştırırken bunu alıyorum. BazıBilgisayar benim.

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)

Eşzamanlı oturum / işlem sayısına ulaşılmış olabilir mi? Herhangi bir fikri olan var mı?


2
Likibaz kilidi tutarken JVM'yi öldürdün mü? Bunun benim için gerçekleştiği tek durum bu.
Christoph Leiter

Başka bir bilgisayar var gibi görünüyor: Konsultpc74. Belki aynı anda farklı PC'lere likibaz koştunuz? Değilse diğer PC için bir açıklama var mı?
Jens

Günlükleri düzenledim ve kazara bunu SomeComputer olarak değiştirmeyi unuttum
Peter Isberg

Değişiklik kümelerini aynı anda mı yürütüyorsunuz? Her dosyanın ve içindeki her değişikliğin tek tek yürütüldüğünü düşündüm. En azından ben bu şekilde kullanıyorum. Ben diğer tüm inlcudes ve everthing tek tek çalıştırılır bir master changeet dosyası var.
Jens

Yanıtlar:


572

Bazen güncelleme uygulaması aniden durdurulursa, kilit takılı kalır.

Sonra koşuyor

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

veritabanı karşı yardımcı olur.

Ya da sadece DATABASECHANGELOGLOCKmasayı bırakabilirsiniz, yeniden oluşturulacaktır.


24
Dışarı geçiş için gerekli 0için FALSE, ama bunun dışında, bu cezayı çalıştı. Teşekkürler
mattalxndr

7
Liquibase'de @Adrian Ber'in cevapladığı şeyi yürütecek releaseLocks adlı yerleşik bir komut var, ancak veritabanı agnostik olduğunu düşünüyorum.

1
Geliştirme ortamımda bu hatayı alıyordum. DATABASECHANGELOGLOCK tablosunu düzeltmek sorunu çözdü.
Naymesh Mistry

1
Ben gerekli için geçmek FALSEiçinb'0'
OrangePot

2
Bu doğru çözümdür, masayı boşaltmaya çalışmayın, çünkü bu yardımcı olmaz. Ya DÜŞÜRÜN ya da KİLİTLİ bayrağı 'YANLIŞ' olarak GÜNCELLE
Aditya T

55

Haziran 2020'yi düzenle

Bu tavsiyelere uymayın. Yıllar boyunca birçok insan için sorun yarattı. Uzun zaman önce benim için çalıştı ve iyi niyetle yayınladım, ama açıkça yapmanın yolu bu değil. DATABASECHANGELOCK tablosunun içinde bir şeyler olması gerekir, bu yüzden sadece her şeyi ondan silmek kötü bir fikirdir.

Örneğin Leos Literak bu talimatları izledi ve sunucu başlatılamadı.

Orijinal cevap

Muhtemelen DATABASECHANGELOGLOCK tablosundaki kilidini serbest bırakmayan öldürülmüş bir likibaz işleminden kaynaklanmaktadır. Sonra,

DELETE FROM DATABASECHANGELOGLOCK;

size yardımcı olabilir.

Edit: @Adrian Ber'in cevabı bundan daha iyi bir çözüm sunuyor. Bunu ancak çözümünü yaparken herhangi bir sorun yaşarsanız yapın.


1
Bu soruya bir cevap sağlamaz. Bir yazardan eleştiri veya açıklama istemek için gönderilerinin altına bir yorum bırakın.
Rachcha

@Rachcha Daha iyi açıkladım. Umarım daha çok beğenirsiniz.
e18r

12
Yukarıdaki tavsiyelere uymayın. DATABASECHANGELOGLOCK, istisnasız herhangi bir satır içermeyen satırlar içermelidir
odedsh

Bu yardımcı olmuyor, tabloyu bırakarak veya kilitli durumu 'yanlış' olarak güncellemek yerine bunu denedim. İşe yaramadı.
Aditya T

Bu yanıtı izlerseniz, gelecekteki komut dosyalarının kilidin var olmasını bekledikleri için çalışmazlar. Bunu zaten yaptıysanız, sorunu çözmek için boş bir kilit ekleyebilirsiniz INSERT INTO yourdb.DATABASECHANGELOGLOCK VALUES (1, 0, null, null);
Rudi Kershaw

24

Sorun, Liquibase'deki SequenceExists'in buggy uygulamasıydı. Bu ifadelerle yapılan değişiklik setleri çok uzun zaman aldığından ve yanlışlıkla iptal edildi. Daha sonra kilidin tutulduğu likibaz betikleri çalıştırmayı deneyin.

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

Bu soruna geçici bir çözüm, bunu denetlemek için düz SQL kullanıyor:

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

Kilit verileri DATABASECHANGELOCK tablosunda saklanır. Kilitten kurtulmak için sadece 1'den 0'a değiştirirsiniz veya o masayı düşürüp yeniden yaratırsınız.


1
Likibaz 3.0.2'de (kullandığım sürüm), bir satırı kilit tablosundan kaldırmayın veya bir dahaki sefere likibaz çalıştırırken farklı bir hatayla karşılaşırsınız çünkü likibaz bir satırın orada olmasını bekler (veya tüm tablo eksik). Tam olarak Peter'ın dediği gibi, sadece bu bilgileri eklemek istedim, çünkü eski sürümlerde satırı kaldırmak için de çalışıyor gibi görünüyor.
Kariem

7

Likibazın yürütülmesi için hangi ortamın kullanıldığı belirtilmemiştir. Spring Boot 2 olması durumunda liquibase.lockservice.StandardLockService, daha temiz olan doğrudan SQL ifadeleri çalıştırmaya gerek kalmadan genişletmek mümkündür . Örneğin:

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

Kod kilidin serbest bırakılmasını zorunlu kılıyor. Bu, hata durumunda yayın çağrısının çağrılmayabileceği test kurulumlarında veya hata ayıklama iptal edildiğinde faydalı olabilir.

Sınıf liquibase.extpakete konulmalıdır ve Spring Boot 2 otomatik yapılandırması tarafından alınacaktır.


Lütfen çözümünüzün daha ayrıntılı bir açıklamasını verebilir misiniz? Spring Boot 2 ve liquibase kullanıyoruz ve db'deki kilit durumunu her seferinde manuel olarak silmek istemiyoruz. Ama ForceReleaseLockService'i sıvıya nasıl enjekte ettiğinizi anlamadım. Bu Bahar'ın birincil fasulye olarak seçtiği bu sınıfa bir Hizmet / Bileşen ek açıklaması koymam gerekmez mi?
Andrej Tihonov

1
Son cümlede belirtilmiştir: "Sınıf liquibase.ext paketine yerleştirilmelidir ve Spring Boot 2 otomatik yapılandırması tarafından alınacaktır."
k_o_

Sınıfı nasıl yerleştiriyorsunuz, liquibase.extprojemde bu paketi tanımlamam gerekiyor mu?
akuma8

Projemde bu paketi tanımladım, işe yarıyor gibi görünüyor ama doğrulayamıyorum. @PostConstructGünlük iletisiyle bir yöntem tanımladım, ancak yazdırıldığını göremiyorum.
akuma8

@ akuma8: Evet, projenizde bu adla bir paket oluşturun. @PostConstructYöntemi nerede tanımladınız ? ForceReleaseLockService'te? Bu bir Bahar servisi değil, bu yüzden bu çağrılan olmayacak.
k_o_

3

Bazen DATABASECHANGELOGLOCK tablosunun kesilmesi veya düşürülmesi işe yaramaz. PostgreSQL veritabanını kullanıyorum ve bu sorunla pek çok kez karşılaştım. Çözmek için yaptığım bu veritabanı için arka planda çalışan hazırlanan ifadeleri geri almaktır. Hazırlanan tüm ifadeleri geri almayı deneyin ve likibaz değişikliklerini tekrar deneyin.

SQL:

SELECT gid FROM pg_prepared_xacts WHERE database='database_name';

Yukarıdaki ifade herhangi bir kayıt döndürürse, bu hazırlanan ifadeyi aşağıdaki SQL ifadesiyle geri alın.

ROLLBACK PREPARED 'gid_obtained_from_above_SQL';

1

Tabloyu manuel olarak veya sorguyu kullanarak güvenle silebilirsiniz. Otomatik olarak yeniden oluşturulur.

DROP TABLE DATABASECHANGELOGLOCK;

0

Bunun OP'nin sorunu olmadığını takdir ediyorum, ancak son zamanlarda farklı bir nedenden dolayı bu sorunla karşılaştım. Referans olarak, SQL Server ile Liquibase Maven eklentisini (liquibase-maven-plugin: 3.1.1) kullanıyordum.

Her neyse, yanlışlıkla bir SQL Server "use" deyimini veritabanlarımı değiştiren komut dosyalarımızdan birine yapıştırdım, böylece liquibase çalışıyor ve güncelleniyor DATABASECHANGELOGLOCK , kilidi doğru veritabanında elde ediyor, ancak değişiklikleri uygulamak için veritabanlarını değiştiriyordu. Değişikliklerimi veya likibaz denetimimi doğru veritabanında göremiyorum, ama elbette, likibazı tekrar çalıştırdığımda, kilit "yanlış" veritabanında serbest bırakıldığı için kilidi alamadı. hala "doğru" veritabanında kilitli. Kilidin serbest bırakılmadan önce hala uygulandığını kontrol etmek için likibaz beklerdim ve belki de bu likibazda bir hata (henüz kontrol etmedim), ancak daha sonraki sürümlerde de ele alınabilir! Bununla birlikte, sanırım bir özellik olarak düşünülebilir!

Biraz okul çocuğu hatası, biliyorum, ama aynı problemle karşılaşması durumunda burada ortaya çıkarıyorum!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.