tablo düzeyinde kilit beklemesini önlemenin yolu


10

Müşterilerimizin veritabanını ekstra bir sunucuya taşıdıktan sonra bir sorunla karşılaştık. Bunun, sitenin performansı üzerinde olumlu etkileri olması gerekirdi, ancak MyISAM'da masa kilitleme ile ilgili bir sorun var. (MyISAM yerine InnoDB kullandığımı duydum, ancak yakın gelecekte motoru değiştiremeyiz).
Bunu, bir moderatör makaledeki bir yorumu etkinleştirdiğinde gerçekleştirilen bir güncelleme sorgusuna tespit edebiliriz. Bu süreç:

  • güncelleme sorgusu işlenir SET status = 1 WHERE id = 5(dizin ayarlanır)
  • sayfanın önbelleğe alınmış dosyaları silinir

Bu noktada tüm sayfa yavaşlar. Veritabanının kendisi dakikalarca meşgul. İşlem listesini birkaç kez aldım ve hepsi tablo düzeyinde kilit bekleyen devlette olan yaklaşık 60 farklı seçme sorgusu girdisi gördüm .

1. Tablodaki bu güncelleştirmenin neden tablo düzeyinde tablo düzeyi kilidini beklemek için article_commentsselect deyimlerini etkileyebileceğini anlamıyorum article. İşlem listesinde neredeyse tüm bekleme sorguları bu tablodan alınmıştır. Güncellemelerin / eklemelerin seçimlere tercih edildiğini ve bu tür sorunlara neden olabileceğini okudum, ancak yorumlar etkinleştirildiğinde makaleler tablosunun kendisi güncellenmiyor, bu yüzden seçimler beklememeliydi. Bunu özledim mi?
2. Bu davranışı önlemek veya en azından daha iyi bir denge kurmak için InnoDB olarak değiştirmenin dışında bir şey var mı? Veritabanını yeni sunucuya taşımadan önce bu sorunun görünmemesi konusunda çok sinirliyim. Bazı yanlış yapılandırmalar var ama nasıl tanımlayacağımı bilmiyorum.


1
Genel günlük kaydını etkinleştirin ve bu tablolar arasında JOIN deyimlerini izleyin. SEÇ seçtiğinizde, kapalı bir OKUMA KİLİTİ oluşturur. MYISAM, ROW LEVEL kilidini desteklemediğinden, tablo düzeyinde kilitlenir. Muhtemelen bu kilitleme eski sunucuda gerçekleşiyordu ama kimse izlemiyordu? My.cnf satırınızı ana bilgisayarlar arasındaki satır için karşılaştırın ve özellikle key_buffer'ınızın doğru ayarlandığından emin olun.
randomx

Eski sunucuda başka performans sorunlarımız vardı ve genellikle işlem listesini izledik. Çoğunlukla uyku süreçleri vardı, ama bekleyenleri fark etmedik (genellikle bu bilgiyi ilk kez bu yeni sunucuda gördüm). Arkadaşım eski my.cnf dosyasını kopyaladı ve değerleri mevcut yeni donanıma göre ayarladı, ancak çok fazla giriş yoktu. Ayrıca "DEĞİŞKENLERİ GÖSTER" in çıktılarını karşılaştırdım, ama neye bakacağımı gerçekten bilmiyordum. Keybuffer'ı yarın tekrar kontrol edeceğiz, yorumunuz için teşekkürler.
32bitfloat

Son zamanlarda benzer bir sorun yaşadık. Başlangıçta bizim key_buffer_sizeolarak ayarlandı 1GB. 10GBSorunu azaltmak için bunu arttırmak .
Haluk

@Rick James, teşekkür ederim. Bugün beni çok sıkıntıdan kurtardın. Amazon'da veya başka bir yerde bir dilek listeniz var mı? :) query_cache_limit 'i 1024 olarak ayarladım. Artık kilit sorunu yok. İlk başta mysql istemcisinden değişkenlerde yaptım. global query_cache_limit = 1024 ayarını yapın; Şimdi my.cnf dosyasına yazacağım. Bu çözüm bana herhangi bir stres olmadan innodb göçünü planlama zamanı geldi, bu yüzden teşekkür ederim.

Yanıtlar:


8

MyISAM Depolama Motoru, herhangi bir DML (INSERT'ler, UPDATE'ler, DELETE'ler) için tam masa kilitleri gerçekleştirmek için öfkeli bir üne sahiptir. InnoDB bu sorunu uzun vadede kesinlikle çözecektir.

MyISAM vs InnoDB kullanmanın artıları ve eksileri hakkında yazdım

Mevcut sorunuzla ilgili olarak, olası bir senaryo:

  • articleve article_commentsher ikisi de MyISAM tabloları
  • article_commentsstatussütun olarak bir veya daha fazla dizine sahip
  • İçin dizin sayfası güncellemeleri article_commentsMyISAM Anahtar Arabelleği'nde ( key_buffer_size boyutunda ) önbelleğe alınır ve eski dizin sayfalarının MyISAM Anahtar Arabelleği dışında kalmasına neden olur
  • Sen arasında JOIN gerçekleştirmek SEÇ sorunuz articlevearticle_comments

Önerilen senaryomda, articletabloya karşı SELECT'ler article_commentsherhangi bir DML'den kurtulmak için beklemek zorunda kaldıkları için yazma işlemlerine izin vermeyebilir (bu durumda, bir UPDATE)


Cevabınız (ve bağlantılar) için teşekkürler, senaryonuz gerçek. Seçme makalenin çoğunun gerçekten yorum tablosuna katılmadığını fark etmedim (veya başka bir deyişle, phpmyadmin işlem listesinde eksik ifadeleri gördü). Birden fazla bekleme sorgusunu önlemek için kısa vadeli bir çözüm biliyor musunuz? Ben zaten belirli bir açıklamada "UPDATE LOW_PRIORITY" ile denedim ama bu fark edilir değişiklikler yapmadı. Gelecekte gerçekten innodb olarak değişeceğiz, ancak şu anda bir iyileşme elde etmenin bir yolu olup olmadığını merak ediyorum.
32bitfloat

Nihai çözüm: Tabloları InnoDB'ye dönüştürün. Benim sonrası Bkz dba.stackexchange.com/a/9422/877 InnoDb ilgili her şeye MyISAM dönüştürmek için nasıl
RolandoMySQLDBA

7

Bu noktada tüm sayfa yavaşlar. Veritabanının kendisi dakikalarca meşgul.

Büyük bir Query_cache'iniz var mı?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

Çok sayıda yazım içeren üretim sistemleri için, query_cache öğesini de KAPALI duruma getirebilirsiniz.

Belirli bir tablo için query_cache içindeki tüm girdiler, o tabloya herhangi bir yazma gerçekleştiğinde temizlenir . KK ne kadar büyük olursa, bu görev o kadar yavaş olur.

MyISAM "tablo seviyesi" kilitler kullanır. Okuma ve yazma aynı anda yapılamaz (aynı tabloda). Kaba ama etkili.


1
İyi evet. Yaklaşık 64 milyon önbellek boyutuna sahibiz. Benim için yeni olan bu bilgi için teşekkürler, ancak biz masa üstü fark etmedi eski sunucuda aynı değeri vardı. Zaten
InnoDB'ye
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.