sposób, aby zapobiec oczekiwaniu zapytań na blokadę poziomu tabeli

10

Napotkaliśmy problem po przeniesieniu bazy danych naszego klienta na dodatkowy serwer. Powinno to mieć pozytywny wpływ na wydajność witryny, ale występuje problem z blokowaniem tabel w MyISAM. (Słyszałem o używaniu InnoDB zamiast MyISAM, ale nie możemy zmienić silnika w najbliższej przyszłości).
Możemy wykryć to w zapytaniu o aktualizację, które jest wykonywane, gdy moderator aktywuje komentarz na stronie artykułów. Oto proces:

  • zapytanie o aktualizację jest przetwarzane SET status = 1 WHERE id = 5(indeks jest ustawiony)
  • buforowane pliki strony są usuwane

W tym momencie cała strona staje się wolna. Sama baza danych jest zajęta przez kilka minut. Pobierałem listę procesów kilka razy i zobaczyłem około 60 wpisów z różnych zapytań select, które były w stanie oczekiwania na blokadę poziomu tabeli .

1. Nie rozumiem, dlaczego ta aktualizacja w tabeli article_commentsmoże wpływać na instrukcje select, aby tabela articleczekała na blokadę na poziomie tabeli. Na liście procesów prawie wszystkie oczekujące zapytania pochodziły z tej tabeli. Czytałem o tym, że aktualizacje / wstawki są lepsze niż selekcje i że może to powodować takie problemy, ale sama tabela artykułów nie jest aktualizowana po aktywowaniu komentarzy, więc selekcje nie powinny czekać. Czy źle to zrozumiałem?
2. Czy jest coś oprócz zmiany na InnoDB, aby zapobiec temu zachowaniu lub przynajmniej uzyskać lepszą równowagę? Jestem bardzo zirytowany faktem, że ten problem nie pojawił się przed przeniesieniem bazy danych na nowy serwer. Wydaje mi się, że jest trochę błędna konfiguracja, ale nie wiem, jak to zidentyfikować.

32bitfloat
źródło
1
Włącz rejestrowanie ogólne i uważaj na instrukcje JOIN między tymi tabelami. Po wybraniu tworzy domyślną BLOKADĘ ODCZYTU. Ponieważ MYISAM nie obsługuje blokowania POZIOMU ​​WIERSZA, blokuje się na poziomie stołu. Prawdopodobnie dzieje się tak, że blokowanie odbywało się na starym serwerze, ale nikt nie obserwował? Porównaj linię my.cnf z linią między hostami, a zwłaszcza upewnij się, że Twój key_buffer jest odpowiednio dostrojony.
randomx
Mieliśmy kilka innych problemów z wydajnością na starym serwerze i często obserwowaliśmy listę procesów. Przeważnie było wiele procesów uśpienia, ale nigdy nie zauważyliśmy czekających (ogólnie te informacje widziałem po raz pierwszy na nowym serwerze). Mój przyjaciel skopiował stary plik my.cnf i dostosował wartości do nowego istniejącego sprzętu, ale nie było wielu wpisów. Porównałem również wyniki „POKAŻ ZMIENNE”, ale tak naprawdę nie wiedziałem, czego szukać. Jutro ponownie sprawdzimy bufor kluczy, dziękuję za komentarz.
32bitfloat
Ostatnio mieliśmy podobny problem. Początkowo nasz key_buffer_sizebył ustawiony na 1GB. Zwiększenie tego, aby 10GBzmniejszyć problem.
Haluk
@Rick James, dziękuję. Zaoszczędziłaś mi dzisiaj wielu kłopotów. Czy masz listę życzeń w Amazon lub gdzieś indziej? :) Ustawiłem query_cache_limit na 1024. Teraz nie ma problemu z blokadą. Zrobiłem to początkowo w zmiennych od klienta mysql. ustaw globalny query_cache_limit = 1024; Teraz napiszę to na my.cnf. To rozwiązanie dało mi czas na zaplanowanie migracji innodb bez stresu, więc dziękuję.

Odpowiedzi:

8

Silnik pamięci masowej MyISAM jest wściekle znany z wykonywania blokad pełnych tabel dla dowolnego DML (INSERT, UPDATEs, DELETE). InnoDB zdecydowanie rozwiąże ten problem w dłuższej perspektywie.

Pisałem o zaletach i wadach korzystania z MyISAM vs InnoDB

Jeśli chodzi o twoje aktualne pytanie, oto możliwy scenariusz:

  • articlei article_commentssą to tabele MyISAM
  • article_commentsma jeden lub więcej indeksów z statusjako kolumną
  • Aktualizacje stron indeksu article_commentssą buforowane w buforze kluczy MyISAM (rozmiar według key_buffer_size ), co powoduje, że stare strony indeksów nie są przechowywane w buforze kluczy MyISAM
  • Masz WYBIERZ zapytania, które wykonują JOIN między articleiarticle_comments

W moim sugerowanym scenariuszu SELECTs względem articletabeli można powstrzymać od zezwolenia na zapisy z powodu konieczności oczekiwania na article_commentsuwolnienie się od dowolnego DML (w tym przypadku an UPDATE)

RolandoMySQLDBA
źródło
Dzięki za odpowiedź (i linki), twój scenariusz jest prawdziwy. Nie zdawałem sobie sprawy, że większość wybranych artykułów rzeczywiście dołącza do tabeli komentarzy (lub innymi słowy, widziałem niepełne instrukcje na liście procesów phpmyadmin). Czy znasz rozwiązanie krótkoterminowe, aby zapobiec wielokrotnym oczekiwaniom? Próbowałem już z „UPDATE LOW_PRIORITY” w konkretnym zestawieniu, ale nie spowodowało to zauważalnych zmian. Naprawdę w przyszłości zmienimy się na innodb, ale zastanawiam się, czy jest jakiś sposób na uzyskanie poprawy.
32bitfloat
Najlepsze rozwiązanie: Konwertuj tabele na InnoDB. Zobacz mój post dba.stackexchange.com/a/9422/877, w jaki sposób przekonwertować wszystko MyISAM na InnoDB
RolandoMySQLDBA
7

W tym momencie cała strona staje się wolna. Sama baza danych jest zajęta przez kilka minut.

Pachnie jakbyś miał dużą pamięć podręczną?

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

W przypadku systemów produkcyjnych z dużą ilością zapisów, równie dobrze możesz WYŁĄCZYĆ cache_pytania.

Wszystkie wpisy w query_cache dla danej tabeli są usuwane, gdy każdy zapis występuje do tej tabeli. Im większa QC, tym wolniejsze jest to zadanie.

MyISAM używa blokad „na poziomie tabeli”. Odczyty i zapisy nie mogą wystąpić w tym samym czasie (na tej samej tabeli). Surowy, ale skuteczny.

Rick James
źródło
1
No tak. Mamy około 64 mln pamięci podręcznej. Dzięki za te informacje, które były dla mnie nowe, jednak mieliśmy tę samą wartość na starym serwerze, na którym nie zauważyliśmy tablelocków. Zaczęliśmy już przenosić się do InnoDB, ale ten fakt pozostaje tajemnicą ...
32bitfloat