Как MySQL таблиците се повреждат? Има много начини за разваляне на файлове с данни. Често корупцията се дължи на дефекти в основната платформа, на която MySQL разчита, за да съхранява и извлича данни - дискова подсистема, контролери, комуникационни канали, драйвери, фърмуер или други хардуерни грешки. Повреждане на данните може да възникне и ако демонът на MySQL сървъра се рестартира внезапно или вашият сървър се рестартира поради срив на други компоненти на ОС. Ако екземплярът на базата данни е бил в средата на записване на данни на диск, той може да запише данните частично, което може да се окаже с контролна сума на страницата, която е различна от очакваната. Има и грешки в MySQL, така че дори хардуерът на сървъра да е наред, самият MySQL може да причини повреда.
Обикновено, когато MySQL данните се повредят, препоръката е да ги възстановите от последното архивиране, да преминете към DR сървър или да премахнете засегнатия възел, ако имате клъстер Galera, който да обслужва данни незабавно от други възли. В някои случаи не можете - ако резервното копие не е там, клъстерът никога не е бил настроен, вашата репликация не работи за много дълго време или процедурата DR никога не е тествана. Дори и да имате резервно копие, все пак може да искате да предприемете някои действия, за да опитате възстановяване, тъй като може да отнеме по-малко време за връщане онлайн.
MyISAM, лошият и грозен
InnoDB е по-устойчив на грешки от MyISAM. InnoDB има функции auto_recovery и е много по-безопасен в сравнение с по-стария MyISAM двигател.
MyISAM таблиците могат лесно да се повредят, когато се случат много записи и много заключвания се случат на тази таблица. Двигателят за съхранение "записва" данни в кеша на файловата система, което може да отнеме известно време, преди да бъде изхвърлено на диска. Следователно, ако вашият сървър се рестартира внезапно, известно неизвестно количество данни в кеша се губи. Това е обичаен начин данните на MyISAM да бъдат повредени. Препоръката е да мигрирате от MyISAM към InnoDB, но може да има случаи, когато това не е възможно.
Primum non nocere, резервното копие
Преди да опитате да поправите повредени таблици, първо трябва да архивирате файловете на базата данни. Да, вече е счупен, но това е с цел да се сведе до минимум рискът от евентуални допълнителни щети, които могат да бъдат причинени от операция по възстановяване. Няма гаранция, че всяко действие, което предприемете, няма да навреди на недокоснатите блокове от данни. Принудителното възстановяване на InnoDB със стойности по-големи от 4 може да повреди файловете с данни, така че се уверете, че ще го направите с предварително архивиране и в идеалния случай на отделно физическо копие на базата данни.
За да архивирате всички файлове от всичките си бази данни, следвайте тези стъпки:
Спрете MySQL сървъра
service mysqld stop
Въведете следната команда за вашия datadir.
cp -r /var/lib/mysql /var/lib/mysql_bkp
След като имаме резервно копие на директорията с данни, сме готови да започнем да отстраняваме неизправности.
Идентификация на повреда в данните
Дневникът на грешките е вашият най-добър приятел. Обикновено, когато се случи повреда на данните, ще намерите подходяща информация (включително връзки към документация) в регистъра за грешки. Ако не знаете къде се намира, проверете my.cnf и променлива log_error, за повече подробности вижте тази статия https://dev.mysql.com/doc/refman/8.0/en/error-log-destination-configuration. html. Това, което също трябва да знаете, е вашият тип двигател за съхранение. Можете да намерите тази информация в регистъра за грешки или в information_schema.
mysql> select table_name,engine from information_schema.tables where table_name = '<TABLE>' and table_schema = '<DATABASE>';
Основните инструменти/команди за диагностициране на проблеми с повреда на данните са CHECK TABLE, REPAIR TABLE и myisamchk. Клиентът mysqlcheck извършва поддръжка на таблици:проверява, поправя (MyISAM), оптимизира или анализира таблици, докато MySQL работи.
mysqlcheck -uroot -p <DATABASE>
Заменете DATABASE с името на базата данни и заменете TABLE с името на таблицата, която искате да проверите:
mysqlcheck -uroot -p <DATABASE> <TABLE>
Mysqlcheck проверява посочената база данни и таблици. Ако дадена таблица премине проверката, mysqlcheck показва OK за таблицата.
employees.departments OK
employees.dept_emp OK
employees.dept_manager OK
employees.employees OK
Employees.salaries
Warning : Tablespace is missing for table 'employees/salaries'
Error : Table 'employees.salaries' doesn't exist in engine
status : Operation failed
employees.titles OK
Проблемите с повреда на данните може да са свързани и с проблеми с разрешенията. В някои случаи ОС може да превключи точката на монтиране в режим само за четене поради проблеми с R/W или това може да бъде причинено от потребител, който случайно е променил собствеността на файловете с данни. В такива случаи ще намерите подходяща информация в регистъра за грешки.
[[email protected] employees]# ls -rtla
...
-rw-rw----. 1 mysql mysql 28311552 05-10 06:24 titles.ibd
-rw-r-----. 1 root root 109051904 05-10 07:09 salaries.ibd
drwxr-xr-x. 7 mysql mysql 4096 05-10 07:12 ..
drwx------. 2 mysql mysql 4096 05-10 07:17 .
MySQL клиент
MariaDB [employees]> select count(*) from salaries;
ERROR 1932 (42S02): Table 'employees.salaries' doesn't exist in engine
Въвеждане в регистъра за грешки
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: Failed to find tablespace for table `employees`.`salaries` in the cache. Attempting to load the tablespace with space id 9
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: Operating system error number 13 in a file operation.
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: The error means mysqld does not have the access rights to the directory.
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: Cannot open datafile for read-only: './employees/salaries.ibd' OS error: 81
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: Operating system error number 13 in a file operation.
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: The error means mysqld does not have the access rights to the directory.
2018-05-10 9:15:38 140703666226944 [ERROR] InnoDB: Could not find a valid tablespace file for `employees/salaries`. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html for how to resolve the issue.
Възстановяване на таблица на InnoDB
Ако използвате механизма за съхранение на InnoDB за таблица на база данни, можете да стартирате процеса на възстановяване на InnoDB.
За да активирате автоматично възстановяване, MySQL се нуждае от опцията innodb_force_recovery да бъде активирана. Innodb_force_recovery принуждава InnoDB да се стартира, като същевременно предотвратява изпълнението на фонови операции, така че да можете да изхвърлите таблиците си.
За да направите това, отворете my.cnf и добавете следния ред към секцията [mysqld]:
[mysqld]
innodb_force_recovery=1
service mysql restart
Трябва да започнете от innodb_force_recovery=1, запишете промените във файла my.cnf и след това рестартирате MySQL сървъра, като използвате съответната команда за вашата операционна система. Ако сте в състояние да изхвърлите вашите таблици със стойност innodb_force_recovery от 3 или по-малко, тогава сте относително в безопасност. В много случаи ще трябва да стигнете до 4 и както вече знаете, това може да повреди данните.
[mysqld]
innodb_force_recovery=1
service mysql restart
Ако е необходимо да промените на по-високата стойност, шест е максималната и най-опасната.
След като можете да стартирате вашата база данни, въведете следната команда, за да експортирате всички бази данни във файла databases.sql:
mysqldump --all-databases --add-drop-database --add-drop-table > dump.sql
Стартирайте mysql и след това опитайте да махнете засегнатата база данни или бази данни, като използвате командата DROP DATABASE. Ако MySQL не може да изтрие база данни, можете да я изтриете ръчно, като използвате стъпките по-долу, след като спрете MySQL сървъра.
service mysqld stop
Ако не сте успели да изтриете база данни, въведете следните команди, за да я изтриете ръчно.
cd /var/lib/mysql
rm -rf <DATABASE>
Уверете се, че не изтривате вътрешните директории на базата данни.
След като сте готови, коментирайте следния ред в [mysqld], за да деактивирате режима за възстановяване на InnoDB.
#innodb_force_recovery=...
Запазете промените във файла my.cnf и след това стартирайте MySQL сървъра
service mysqld start
Въведете следната команда, за да възстановите базите данни от архивния файл, който сте създали в стъпка 5:
mysql> tee import_database.log
mysql> source dump.sql
Поправяне на MyISAM
Ако mysqlcheck отчете грешка за таблица, въведете командата mysqlcheck с флаг -repair, за да я поправите. Опцията за поправка на mysqlcheck работи, докато сървърът работи и работи.
mysqlcheck -uroot -p -r <DATABASE> <TABLE>
Ако сървърът не работи и по някаква причина mysqlcheck не може да поправи вашата таблица, все още имате възможност да извършите възстановяване директно на файлове с помощта на myisamchk. С myisamchk трябва да се уверите, че сървърът няма отворени таблици.
Спрете MySQL
service mysqld stop
cd /var/lib/mysql
Променете към директорията, където се намира базата данни.
cd /var/lib/mysql/employees
myisamchk <TABLE>
За да проверите всички таблици в база данни, въведете следната команда:
myisamchk *.MYI
Ако предишната команда не работи, можете да опитате да изтриете временни файлове, които може да пречат на myisamchk да работи правилно. За да направите това, върнете се обратно към директорията с данни и след това изпълнете следната команда:
ls */*.TMD
Ако има изброени .TMD файлове, изтрийте ги:
rm */*.TMD
След това стартирайте отново myisamchk.
За да опитате да поправите таблица, изпълнете следната команда, като замените TABLE с името на таблицата, която искате да поправите:
myisamchk --recover <TABLE>
Рестартирайте MySQL сървъра
service mysqld start
Как да избегнем загуба на данни
Има няколко неща, които можете да направите, за да сведете до минимум риска от невъзстановими данни. Преди всичко архивиране. Проблемът с архивирането е, че понякога те могат да бъдат пренебрегнати. За планирано архивиране на cron обикновено пишем скриптове за обвивка, които откриват проблеми в архивния регистър, но това не включва случаите, когато архивирането изобщо не е започнало. Cron понякога може да виси и често няма настроен мониторинг върху него. Друг потенциален проблем може да бъде случаят, когато архивирането никога не е било настроено. Добрата практика е да стартирате отчети от отделен инструмент, който ще анализира състоянието на архивиране и ще ви информира за липсващи графици за архивиране. Можете да използвате ClusterControl за това или да напишете свои собствени програми.
Оперативният отчет за архивиране на ClusterControlЗа да намалите въздействието на възможното повреждане на данните, винаги трябва да обмисляте клъстерни системи. Въпрос на време е кога базата данни ще се срине или ще се повреди, така че е добре да имате копие, към което да превключите. Може да е репликация главен/подчинен. Важният аспект тук е да има безопасно автоматично възстановяване, за да се сведе до минимум сложността на превключването и да се сведе до минимум времето за възстановяване (RTO).
Функции за автоматично възстановяване на ClusterControl