Czy istnieje płynny lub bezpieczny restart dla mysql, np. Dla apache httpd?

29

Chciałbym z wdziękiem zrestartować mysql, tak jak httpd, gdzie wątki są obsługiwane przed restartem. Nie chciałbym łamać zapytań.

giorgio79
źródło

Odpowiedzi:

37

Każda „żądana” sekwencja zamykania w MySQL (brak kill -9) jest nieco wdzięczna , ponieważ trwające transakcje (w tabelach transakcyjnych) są wycofywane, ale oto kilka sposobów, aby ponowne uruchomienie było tak czyste, jak to możliwe.

Uwaga: jeśli zamykasz serwer w celu aktualizacji, nie korzystaj z tego procesu; zamiast tego postępuj zgodnie z procesem opisanym w tej odpowiedzi .

W przeciwnym razie, jeśli ponownie uruchamiasz serwer w inny sposób, aby zmienić globalną zmienną tylko do odczytu lub coś podobnego, oto wdzięczna ścieżka:

Najpierw włącz, innodb_fast_shutdownjeśli jeszcze nie jest. Nie jest to bezpośrednio związane z wdziękiem zamknięcia, ale powinno przyspieszyć powrót serwera.

mysql> SHOW VARIABLES LIKE 'innodb_fast_shutdown';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| innodb_fast_shutdown | 0     |
+----------------------+-------+
1 row in set (0.00 sec)

mysql> SET GLOBAL innodb_fast_shutdown = 1;
Query OK, 0 rows affected (0.01 sec)

Następnie poinstruuj serwer, aby zamykał wszystkie otwarte tabele, gdy tylko odwołują się do nich obecnie uruchomione zapytania. Ten krok nie ma również nic wspólnego z płynnym zamykaniem, ale sprawi, że kolejny krok będzie przebiegał szybciej:

mysql> FLUSH LOCAL TABLES;
Query OK, 0 rows affected (41.12 sec)

FLUSH TABLESOświadczenie (z opcjonalnym LOCALsłów kluczowych, co pozwala uniknąć niepotrzebnego ale inaczej nieszkodliwe przypływ wszelkich niewolników) zablokuje a szybka wola nie wrócić aż wszystkie tabele mogą być zamknięte. Gdy każda tabela zostanie „opróżniona” (zamknięta), jeśli zapytanie odwołuje się następnie do tabeli, zostanie ona automatycznie ponownie otwarta, ale to w porządku. Na tym etapie osiągamy mniej pracy przy ostatnim kroku:

mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (13.74 sec)

mysql>

Ta instrukcja opróżnia wszystkie tabele (stąd korzyść polegająca na tym, że niektóre z nich mniej przeszkadzają w poprzednim kroku) i uzyskuje globalną (tylko dla serwera) blokadę tylko do odczytu.

Nie możesz mieć globalnej blokady odczytu, dopóki nie zostanie wykonane każde aktualnie uruchomione zapytanie „zapisz” (tzn. Prawie wszystko oprócz SELECT). Wysłanie żądania blokady pozwoli na zakończenie istniejących zapytań, ale nie pozwoli na uruchomienie nowych.

Twoje zapytanie nie powróci, dopóki nie przytrzymasz tej globalnej blokady, więc każde zapytanie, które jest w toku, gdy poprosisz o blokadę, może zakończyć się i wiesz, że zostały zakończone, ponieważ otrzymujesz monit z powrotem. Wszelkie kolejne zapytania, które próbują zapisać cokolwiek w dowolnej tabeli, po prostu utkną w miejscu, nie będą zmieniać danych, będą czekać w nieskończoność na blokadę, dopóki ...

  • zmienisz zdanie na temat ponownego uruchomienia i zwolnisz blokadę ręcznie ( UNLOCK TABLES;)
  • zrestartujesz serwer, lub
  • przypadkowo lub celowo odłączasz klienta linii poleceń od tego wątku (więc nie rób tego). Pozostaw to okno podłączone i wyświetlane po monicie mysql:

Oprzyj się pokusie zamknięcia tego.

mysql>

To pytanie o bezczynną konsolę blokuje globalną blokadę. Strać to, stracić zamek.

Z innego okna konsoli zrestartuj MySQL w normalny sposób, albo za pomocą skryptów startowych (np. Lokalny wariant service mysql.server restart), albo mysqladmin shutdownręcznie, po którym nastąpi restart.

Michael - sqlbot
źródło
Czy używanie innodb_fast_shutdown = 1naprawdę zapewnia, że ​​MySQL uruchamia się szybciej? Patrząc na dokumenty, wydaje się, że poprawia to szybkość zamykania (kosztem prędkości uruchamiania?).
Chris
@Chris pomysł polega na tym, że pomaga zapewnić, że całe zamknięcie + uruchomienie jest tak szybkie, jak to praktyczne, ale jest to nieco anegdotyczne, ponieważ ilość wykonywanej pracy jest teoretycznie taka sama - właśnie przeniesiona na drugą stronę sekwencji - jeszcze z jakiegoś powodu zawsze wydawało się ogólnie szybsze, na przykład być może istnieje pewna nieefektywność w sposobie, w jaki się dzieje przy wyłączaniu, którego nie ma przy starcie. Ciężko powiedzieć.
Michael - sqlbot
2

Krótko mówiąc, niektóre z najlepszych praktyk, które należy wziąć pod uwagę przed zamknięciem MySQL to:

  1. Potwierdź instancję, którą chcesz zamknąć, aby uniknąć przypadkowego zatrzymania innej instancji.
  2. Zatrzymaj replikację, jeśli zamierzasz zamknąć slave mysql> STOP SLAVE;.
  3. Opróżnij wcześniej brudne strony, aby skrócić czas wyłączania mysql> SET GLOBAL innodb_max_dirty_pages_pct = 0;.
  4. Sprawdź długo działające zapytania mysql> SHOW PROCESSLIST;, zabij je mysql> kill thread_id;lub poczekaj, aż zakończą.
  5. Zrzuć pulę buforów podczas zamykania mysql> SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;i załaduj ją ponownie podczas uruchamiania, # vi /etc/my.cnf innodb_buffer_pool_load_at_startup = ON aby rozgrzać pulę buforów.

Następnie po potwierdzeniu poprzednich punktów możesz bezpiecznie ponownie uruchomić MySQL shell$ service mysql restart

Aby uzyskać więcej informacji, zobacz mój post Sprawdź je przed wyłączeniem MySQL!

Moll
źródło
Dlaczego zostało to zanegowane? Nie wiem wystarczająco, aby rozpoznać, które polecenia są złe, ale chcę wiedzieć, aby ich uniknąć.
Jon
Nie wiem, czy którekolwiek z powyższych jest złym poleceniem. Postępuję zgodnie z powyższymi krokami i tak robi wiele osób. Tylko krok 4 powinien być ostrożny, nie powinieneś zabijać żadnych zapytań, dopóki nie będziesz pewien, co robisz, w przeciwnym razie poczekaj, aż zakończą się długo działające zapytania. Spróbuj, a jeśli to pomogło, oceń go, jeśli nie, oceń go!
Moll