Dlaczego awarie tabel MySQL? Jak temu zapobiec?

9

Jestem administratorem strony Moodle, która ma uszkodzoną tabelę Użytkownicy i stała się bezużyteczna.

Na szczęście prosty REPAIR TABLE mdl_userprzywrócił go do działania. Chodzi o to, że nie wiem, dlaczego tak się zawiesiło i sprawiło, że nie nadaje się do użytku, i chcę się upewnić, że następnym razem będę lepiej przygotowany.

Nie jestem dogłębnie doświadczonym DBA - jestem tylko programistą, który robi wiele rzeczy, więc proszę o wyrozumiałość.

Mógłbym po prostu przywrócić kopię zapasową, ale myślę, że istnieją sposoby zapobiegania awariom.

Te tabele to utf8_general_ci i używają MyISAM.

Dlaczego awaria tabeli MySQL? Co mogę zrobić, aby temu zapobiec?

AeroCross
źródło

Odpowiedzi:

11

Awaria tabeli MyISAM jest raczej łatwa.

W nagłówku każdej tabeli MyISAM znajduje się licznik, który śledzi liczbę otwartych uchwytów plików względem tabeli.

Jeśli uruchomisz mysql, a liczba w nagłówku nie odpowiada liczbie rzeczywistych uchwytów plików, mysqld traktuje tabelę jako zawieszoną.

Jeśli prosty REPAIR TABLE mdl_usersprawia, że ​​działa on ponownie za każdym razem bez utraty danych, może to oznaczać, że masz witrynę o bardzo dużym natężeniu ruchu, która pisze mdl_user.

Jeśli wymagają tego dziesiątki tabel REPAIR TABLE, przekonwertowałbym wszystkie tabele na InnoDB. Jeśli jednak mdl_usertabela jest jedyną tabelą z tym problemem, można coś zrobić (w tym przykładzie powiedzmy, że baza danych jest moodle);

Jeśli chcesz, aby wszystkie tabele pozostały jako MyISAM

KROK 01: Utwórz skrypt tabeli naprawy

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

KROK 02: Zadeklaruj skrypt naprawczy jako plik startowy

Dodaj to do /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

KROK 03: Uruchom ponownie mysql

Każde ponowne uruchomienie mysql spowoduje uruchomienie skryptu naprawy tabeli

Jeśli chcesz, aby wszystkie tabele stały się InnoDB

Uruchom ten kod, aby utworzyć skrypt konwersji zbiorczej tabel MyISAM do InnoDB, i wyświetl go

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

Gdy będziesz zadowolony z zawartości skryptu konwersji, uruchom go

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

AKTUALIZACJA 2012-03-15 14:00 EDT

@Kevin , Co zrobić, jeśli korzystasz z MyISAM?

Oto kilka rzeczy do rozważenia: Zgodnie z MySQL 5.0 Certification Study Guide ,

wprowadź opis zdjęcia tutaj

punkt 11 mówi: na stronach 408, 409, sekcja 29.2:

Jeśli zabraknie miejsca na dysku podczas dodawania wierszy do tabeli MyISAM, nie wystąpi błąd. Serwer zawiesza operację, dopóki przestrzeń nie będzie dostępna, a następnie kończy operację.

Kiedy zabraknie miejsca na dysku, nie wyłączaj ani nie zabijaj mysql. Liczba uchwytów otwartych plików w aktualnie używanym MyISAM nie zostanie wyczyszczona. Tak więc tabela MyISAM jest oznaczona jako rozbita. Jeśli możesz zwolnić miejsce na dysku w woluminie danych, gdy mysqld nadal działa, mysqld wykona połączenie po udostępnieniu miejsca na dysku.

RolandoMySQLDBA
źródło
Doskonała odpowiedź. Nie znałem nieco uchwytów plików, a już rozwiązałeś, jak mogę zapobiec (lub automatycznie naprawić) na wypadek, gdyby coś poszło nie tak. Wszelkie sugestie dotyczące bezpieczeństwa, jeśli strona faktycznie zapisuje wiele do mdl_user (lub innej tabeli)?
AeroCross
Powinieneś zrobić trzy rzeczy: 1) zwiększyć RAM, 2) zwiększyć max_connections, 3) przełączyć na InnoDB.
RolandoMySQLDBA
Noob tutaj. Gdzie mogę „uruchomić” ten kod? Z pliku przesłanego na serwer lub z linii poleceń?
UncaughtTypeError
0

Zarządzam także witryną moodle na mysql, a najczęstszą przyczyną uszkodzenia tabeli jest brak miejsca na dysku.

Kevin
źródło
@RolandoMySQLDBA - tak, z pewnością problemem jest miejsce na dysku (związane z innymi procesami i ogólnie filozofią zarządzania). Niestety nie widzimy problemu, który rozwiązuje się sam, gdy przestrzeń jest pusta, lub nie rozwiązuje się w odpowiednim czasie. Moja odpowiedź polegała tylko na wskazaniu, że z naszą instancją moodle / mysql problemy z miejscem na dysku mogą powodować awarie tabel, niezależnie od tego, co ma zrobić mysql / myisam.
Kevin,
-3

Znalazłem jedną dobrą linię do konwersji wszystkich tabel na InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName
Dmitry
źródło
Kod może być do tego odpowiedni, ale nie odpowiada na pytanie z pierwszej części (Dlaczego awaria tabeli MySQL?). Jeśli masz na myśli, że odpowiada on na drugą część (Jak temu zapobiec?), Proszę dodaj więcej wyjaśnień.
ypercubeᵀᴹ
Dodaj także więcej szczegółów. Czy uruchomienie tego przekształci wszystkie tabele w bazie danych? Czy cały serwer? Co się stanie, jeśli tabela nie zostanie przekonwertowana i wystąpi błąd? Czy to możliwe, że skończymy z niektórymi tabelami przekonwertowanymi, a niektóre pozostawione w MyiSAM? Zasadniczo, jakie inne rzeczy powinien rozważyć DBA przed uruchomieniem tego?
ypercubeᵀᴹ