"Kilit bekleme zaman aşımı aşıldı; "sıkışmış" bir Mysql tablosu için "işlemi yeniden başlatmayı deneyin.


131

Bir komut dosyasından yerel veritabanıma binlerce kez bunun gibi bir sorgu gönderdim:

update some_table set some_column = some_value

Nerede bölümünü eklemeyi unuttum, bu nedenle aynı sütun tablodaki tüm satırlar için aynı değere ayarlandı ve bu binlerce kez yapıldı ve sütun dizine eklendi, bu nedenle ilgili dizin muhtemelen çok fazla kez güncellendi .

Bir şeylerin yanlış olduğunu fark ettim çünkü çok uzun sürdü, bu yüzden senaryoyu öldürdüm. O zamandan beri bilgisayarımı bile yeniden başlattım, ancak tabloda bir şey sıkışmış, çünkü basit sorguların çalışması çok uzun sürüyor ve ilgili dizini bırakmaya çalıştığımda şu mesajla başarısız oluyor:

Lock wait timeout exceeded; try restarting transaction

Bu bir innodb tablosu, bu nedenle takılı kalmış işlem muhtemelen örtüktür. Bu tabloyu nasıl düzeltebilirim ve sıkışan işlemi ondan nasıl kaldırabilirim?


3
Çıktısı nedir SHOW FULL PROCESSLIST?
Wolph

Yalnızca SHOW FULL PROCESSLIST komutunu gösterir, başka hiçbir şey göstermez. Yerel bir geliştirme veritabanıdır. Üzerinde hiçbir şey çalışmıyor. Dizini oradan bırakmayı denediğimde komut satırında 'kilitle bekle ..' hata mesajını aldım.
Tom

Bu durumda muhtemelen farklı işlemlerde birbirini beklemesi gereken 2 ayrı bağlantı oluşturuyorsunuz.
Wolph

Daha sonra herhangi bir işlem oluşturmadım. Komut dosyasını öldürdüm, makineyi yeniden başlattım ve etrafa bakmak için komut satırından oturum açtım. Veritabanını mysql komut satırı istemcisi dışında başka hiçbir şey kullanmadı, bu nedenle tabloda bir şey sıkışmış olmalı.
Tom

Yanıtlar:


143

Benzer bir sorun yaşadım ve çalışan konuları kontrol ederek çözdüm. Çalışan iş parçacıklarını görmek için mysql komut satırı arayüzünde aşağıdaki komutu kullanın:

SHOW PROCESSLIST;

Mysql komut satırı arayüzüne erişiminiz yoksa phpMyAdmin'den de gönderilebilir.
Bu, karşılık gelen kimlikleri ve yürütme süresine sahip iş parçacıklarının bir listesini görüntüler, böylece yürütmesi çok fazla zaman alan iş parçacıklarını ÖLDÜRebilirsiniz. PhpMyAdmin'de, KILL kullanarak iş parçacıkları durdurmak için bir düğmeye sahip olacaksınız, eğer komut satırı arayüzünü kullanıyorsanız, sadece KILL komutunu ve ardından aşağıdaki örnekte olduğu gibi iş parçacığı kimliğini kullanın:

KILL 115;

Bu, ilgili iş parçacığı için bağlantıyı sonlandıracaktır.


36
NOT ALIN! Bu, bu sorunla ilgili birçok SO iş parçacığından biri tarafından belirtildi: Bazen tabloyu kilitleyen işlem, işlem listesinde uyuyor olarak görünür! Uyuyor olsun ya da olmasın söz konusu veritabanında açık olan tüm konuları öldürene kadar saçlarımı yırtıyordum. Bu, sonunda tablonun kilidini açtı ve güncelleme sorgusunun çalışmasına izin verdi. Yorumcu, "Bazen bir MySQL iş parçacığı bir tabloyu kilitler, sonra MySQL ile ilgili olmayan bir şeyin olmasını beklerken uyur" gibi bir şeyden bahsetti.
Eric L.

( İlgili soru üzerine, buradaki düşünce parçasını ortaya çıkarmak için kendi cevabımı ekledim )
Eric L.

Bu bana yardımcı oldu. PHPStorm veritabanı yönetimi / sorgu özelliği tarafından oluşturulan birkaç uyku iş parçacığım vardı .
Ejaz

Harika! Tanımlayıp öldürebildiğim 5 saatten beri gizli bir süreç geçirdim.
Aldo Paradiso

2
bu bir çözüm değildir, enfekte bir yaranın üzerine kanal bantlamanın bir çözüm olmasından başka bir şey değildir. altta yatan temel sorunu ele almıyorsunuz.
user2914191

55

Şu anda devam eden işlemleri kontrol edebilirsiniz.

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`

İşleminiz listedeki en eskisi olduğu için ilk işlemlerden biri olmalıdır. Şimdi sadece değeri al trx_mysql_thread_idve ona şu KILLkomutu gönder :

KILL 1234;

Hangi işlemin size ait olduğundan emin değilseniz, ilk sorguyu çok sık tekrarlayın ve hangi işlemlerin devam ettiğini görün.


Hangi işlemin diğerinin tabloya erişmesini gerçekten engellediğini görmek için bu SQL'i çalıştırmak için kök hesabı kullanmanız gerekebilir
tom10271

40

InnoDB durumunu kilitler için kontrol edin

SHOW ENGINE InnoDB STATUS;

MySQL açık tablolarını kontrol edin

SHOW OPEN TABLES WHERE In_use > 0;

Bekleyen InnoDB işlemlerini kontrol edin

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

Kilit bağımlılığını kontrol edin - neyi engeller

SELECT * FROM `information_schema`.`innodb_locks`;

Yukarıdaki sonuçları inceledikten sonra, neyin neyi kilitlediğini görebilmelisiniz.

Sorunun temel nedeni kodunuzda da olabilir - lütfen Hazırda Bekletme gibi JPA kullanıyorsanız, özellikle ek açıklamalar için ilgili işlevleri kontrol edin.

Örneğin, burada açıklandığı gibi , aşağıdaki ek açıklamanın kötüye kullanılması veritabanında kilitlere neden olabilir:

@Transactional(propagation = Propagation.REQUIRES_NEW) 

4
Çok teşekkür ederim! Çalıştırmak SELECT * FROM information_schema.innodb_trx t JOIN information_schema.processlist p ON t.trx_mysql_thread_id = p.idsuçluyu ortaya çıkardı: Kilitleme iş parçacığı IP adresimden geldi ... Bir işlemin ortasında bıraktığım bir hata ayıklama konsolunu kapatmayı unutmuştum ...
Elias Strehle

40

Bu, veritabanı boyutum büyüdüğünde ve üzerinde çok fazla işlem yaptığımda başıma gelmeye başladı.

Gerçek şu ki, sorgularınızı veya DB'nizi optimize etmenin muhtemelen bir yolu vardır, ancak bu 2 sorguyu bir çözüm için deneyin.

Bunu çalıştırın:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

Ve sonra bu:

SET innodb_lock_wait_timeout = 5000; 

2
Referans bağlantı: innodb_lock_wait_timeout
culix

1
Çok yoğun bir 11GB veritabanı çalıştırıyorum. Bu benim için işe yarayan tek şey, teşekkür ederim!
dongemus

Sonsuza kadar orada tutmak istemiyorsanız, değerleri önceki değerlerine değiştirmeyi unutmayın.
Ricardo Martins

Bu, bazı kullanıcılarımın daha yavaş bir deneyime sahip olacağı anlamına geliyor, değil mi?
Arnold Roa

9

Bir işlem için bağlantı kurduğunuzda, işlemi gerçekleştirmeden önce bir kilit alırsınız. Kilidi alamazsanız, bir süre denersiniz. Kilit hala elde edilemezse, kilit bekleme süresi aşıldı hatası atılır. Neden bir kilit alamıyorsunuz, bağlantıyı kapatmıyorsunuzdur. Bu nedenle, ikinci kez kilit almaya çalıştığınızda, önceki bağlantınız hala kapalı olduğundan ve kilidi tuttuğundan kilidi alamazsınız.

Çözüm: Bağlantıyı kapatın veya setAutoCommit(true)kilidi açmak için (tasarımınıza göre).


7

MySQL'i yeniden başlatın, sorunsuz çalışıyor.

ANCAK , böyle bir sorgu sıkışırsa, bir yerde bir sorun olduğuna dikkat edin:

  • sorgunuzda (yanlış yerleştirilmiş karakter, kartezyen ürün, ...)
  • düzenlenecek çok sayıda kayıt
  • karmaşık birleşimler veya testler (MD5, alt dizeler LIKE %...%, vb.)
  • veri yapısı sorunu
  • yabancı anahtar modeli (zincir / döngü kilitleme)
  • misindexed veriler

@Syedrakib'in dediği gibi işe yarıyor ama bu üretim için uzun ömürlü bir çözüm değil.

Dikkat: yeniden başlatma yapmak, verilerinizi tutarsız durumda etkileyebilir.

Ayrıca, MySQL'in EXPLAIN anahtar sözcüğü ile sorgunuzu nasıl işlediğini kontrol edebilir ve orada sorguyu hızlandırmak için bir şeylerin mümkün olup olmadığını görebilirsiniz (dizinler, karmaşık testler, ...).


TEŞEKKÜR EDERİM. sorunumu doğrudan çözmediniz ama masa kilitlerinden muzdariptim ve çok kötüydü. Bu, tüm internetteki tek gönderi, bu da beni yabancı anahtarları kontrol etme fikrine götürüyor. Böylece birincil anahtarın 11 ve yabancı anahtarların 10 olduğunu öğrendim. Bunun nasıl olabileceğini ve daha önce neden her şeyin çalıştığını bilmiyorum.
EscapeNetscape

@EscapeNetscape rica ederim, bu küçük cevabın size yardımcı olmasına sevindim :)
Benj

3

Mysql'de işlemlere gidin.

Gördüğünüz gibi hala görev var.

Belirli işlemi sonlandırın veya işlem tamamlanana kadar bekleyin.


7
Sorunu çözer. Ancak bu CANLI bir üretim sunucusu için bir çözüm olamaz ...... Bu kilitlenme işleminin sonucunu nasıl çıkarabiliriz? Ya da bu çıkmazdan nasıl kaçınabiliriz?
Rakib

1
Aslında, geliştirici tarafından yazılmayan, ancak çerçevenin aktif kayıt arabirimi tarafından yazılan MÜKEMMEL ŞEKİLDE iyi biçimlendirilmiş ve MÜKEMMEL bir şekilde kaçmış mysql sorgularında bile, kilit bekleme zaman aşımı sorunları HALA gerçekleşebilir. Bu yüzden uygun mysql sorgusu yazmıyorum burada bir faktör.
Rakib

1

Aynı sorunu bir "güncelleme" ifadesiyle karşılaştım. Benim çözümüm, tablo için phpMyAdmin'de mevcut olan işlemleri yürütmekti. Tabloyu optimize ettim, temizledim ve birleştirdim (bu sırayla değil). Benim için tabloyu bırakıp yedekten geri yüklemenize gerek yok. :)


1
Sorunu çözebilir. Ancak bu tür bir hata her oluştuğunda bunu yapmak zorunda kalmak CANLI bir üretim sunucusu için bir çözüm olamaz ...... Bu kilitlenme işleminin çıktısını nasıl verebiliriz? Ya da bu çıkmazdan nasıl kaçınabiliriz?
Rakib

1

Ben de aynı sorunu yaşadım. Bunun SQL ile ilgili bir kilitlenme sorunu olduğunu düşünüyorum. Görev Yöneticisi'nden SQL işlemini kapatmaya zorlayabilirsiniz. Bu sorunu çözmediyse, bilgisayarınızı yeniden başlatmanız yeterlidir. Tabloyu bırakıp verileri yeniden yüklemenize gerek yoktur.


Sorunu çözer. Ancak bu CANLI bir üretim sunucusu için bir çözüm olamaz ...... Bu kilitlenme işleminin sonucunu nasıl çıkarabiliriz? Ya da bu çıkmazdan nasıl kaçınabiliriz?
Rakib

Apache'yi ve hizmetlerini (veya en azından MySQL'i) yeniden başlatın, yeniden başlatmaya gerek yok
Amjo

1

Belirli bir kayıt grubunu silmeye çalışırken bu sorunu yaşadım (MS Access 2007'yi bir web sunucusunda MySQL'e ODBC bağlantısı ile kullanarak). Tipik olarak, MySQL'den belirli kayıtları silerim ve daha sonra güncellenmiş kayıtlarla değiştirirdim (birkaç ilişkili kaydı kademeli olarak silerim, bu tek bir kayıt silme için ilgili tüm kayıtları silmeyi kolaylaştırır).

Tablo için phpMyAdmin'de bulunan işlemleri çalıştırmayı denedim (optimize etme, temizleme, vb.), Ancak temizlemeyi denediğimde YENİDEN YÜKLEME hatasına ihtiyaç izni alıyordum. Veritabanım bir web sunucusunda olduğu için veritabanını yeniden başlatamadım. Bir yedeklemeden geri yüklemek bir seçenek değildi.

Web üzerindeki cPanel mySQL erişiminde bu kayıt grubu için silme sorgusu çalıştırmayı denedim. Aynı hata mesajını aldım.

Çözümüm: Sun'ın (Oracle'ın) ücretsiz MySQL Sorgu Tarayıcısını (daha önce bilgisayarıma yüklediğim) kullandım ve silme sorgusunu orada çalıştırdım. Hemen işe yaradı, Sorun çözüldü. Daha sonra, ODBC Access to MySQL bağlantısını kullanarak Access komut dosyasını kullanarak işlevi bir kez daha gerçekleştirebildim.


-2

Onu düzeltti.

Sorguda eşleşmeyen veri türü eklemediğinizden emin olun. "Kullanıcı tarayıcı aracısı verilerini" denediğim VARCHAR(255)ve bu kilitle ilgili sorun yaşadığım bir sorunla karşılaştım, ancak onu değiştirdiğimde TEXT(255)düzelttim.

Bu nedenle büyük olasılıkla bir veri türü uyuşmazlığıdır.


-151

Tabloyu bırakıp yedekten geri yükleyerek sorunu çözdüm.


20
Bu arada, bu cevap SO'nun Tüm Zamanların En Düşük Skorlu "Kabul Edilen" Cevabı olma onurunu kazanıyor ! 🏆
ashleedawg

1
Bu aynı zamanda genel olarak en düşük puanlı cevaptır
Bob Kerman
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.