Чому збиваються таблиці MySQL? Як мені це запобігти?


9

Я адміністратор сайту Moodle, у якого пошкоджена таблиця користувачів, і вона стала непридатною.

На щастя, простий REPAIR TABLE mdl_userзмусив його знову працювати. Вся справа в тому, що я не знаю, чому він насправді розбився і зробив його непридатним, і я хочу переконатися, що я краще підготуюся наступного разу.

Я не є досвідченим DBA - я просто розробник, який робить багато речей, тому будь ласка, будьте зі мною.

Я міг би просто відновити резервну копію, але, мабуть, є способи запобігти збоям.

Ці таблиці є utf8_general_ci та використовують MyISAM.

Чому відбувається збій таблиці MySQL? Що я можу зробити, щоб цього не сталося?

Відповіді:


11

Таблиця MyISAM доволі проста.

У заголовку кожної таблиці MyISAM є лічильник, який відстежує кількість відкритих файлових файлів проти таблиці.

Якщо ви запускаєте mysql і число в заголовку не відповідає кількості фактичних ручок файлу проти, mysqld обробляє таблицю як збій.

Якщо звичайний REPAIR TABLE mdl_userзмушує його працювати кожен раз без втрати даних, це може вказувати на те, що у вас є дуже сильно проданий сайт, на який пишеться mdl_user.

Якщо цього потребують десятки таблиць REPAIR TABLE, я перетворив би всі таблиці в InnoDB. Однак якщо mdl_userтаблиця є єдиною таблицею з цією проблемою, ви можете щось зробити (для цього прикладу, скажімо, база даних moodle);

Якщо ви хочете, щоб усі таблиці залишилися як MyISAM

КРОК 01: Створіть сценарій відновлення таблиці

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

КРОК 02: Оголосіть сценарій відновлення як файл запуску

Додайте це до /etc/my.cnf

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

КРОК 03: Перезапустіть mysql

Кожен перезапуск mysql запускає сценарій відновлення таблиці

Якщо ви хочете, щоб усі таблиці стали InnoDB

Запустіть цей код, щоб скласти скрипт масового перетворення таблиць MyISAM в InnoDB та переглянути його

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

Після того, як ви задоволені вмістом сценарію перетворення, запустіть його

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

ОНОВЛЕННЯ 2012-03-15 14:00 EDT

@Kevin , використовуючи MyISAM, що робити, якщо у вас вичерпано місце на диску?

Ось що слід врахувати: Відповідно до посібника з вивчення сертифікації MySQL 5.0 ,

введіть тут опис зображення

bulletpoint № 11 на Стор. 408 409 Розділ 29.2 говорить наступне:

Якщо у вас не вистачає місця на диску, додаючи рядки до таблиці MyISAM, помилка не виникає. Сервер призупиняє операцію, поки не стане доступним простір, а потім завершить операцію.

Коли у вас не вистачає місця на диску, не просто вимикайте та не вбивайте mysql. Кількість ручок відкритого файлу в будь-якому використовуваному в даний час MyISAM не буде очищено. Таким чином, таблиця MyISAM позначена крашкою. Якщо ви можете звільнити місце на диску в обсязі даних, коли mysqld все ще запущений, mysqld виведе на екран, коли доступний простір на диску.


Відмінна відповідь. Ви не знали біт файлів, і ви вже вирішили, як я можу запобігти (або автоматично відремонтувати), якщо щось піде не так. Будь-яка пропозиція щодо безпеки, якщо сайт насправді багато пише на mdl_user (або будь-яку іншу таблицю)?
AeroCross

Вам слід зробити три речі: 1) збільшити оперативну пам’ять, 2) збільшити max_connections, 3) перейти на InnoDB.
RolandoMySQLDBA

Нуб тут. Де я "запускаю" цей код? З файлу, завантаженого на сервер, або з якогось командного рядка?
UncaughtTypeError

0

Я також адмініструю настрій настрою на mysql, і найпоширенішою причиною корупції для нас є відсутність місця на диску.


@RolandoMySQLDBA - так, дисковий простір - це, безумовно, проблема (пов'язана з деякими іншими процесами та філософією управління загалом). На жаль, ми не бачимо, що проблема вирішується сама, коли очищується простір, або вона не вирішує себе досить вчасно. Моя відповідь полягала лише в тому, щоб вказати, що в нашому екземплярі moodle / mysql проблеми з дисковим простором можуть спричинити збої в таблиці, незалежно від того, що передбачається робити mysql / myisam.
Кевін

-3

Я знайшов один хороший рядок для перетворення всіх таблиць у 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

Код для цього може бути нормальним, але він не відповідає на питання першої частини (Чому таблиця MySQL виходить з ладу?). Якщо ви хочете сказати, що він відповідає на другу частину (Як запобігти?), Додайте ще трохи пояснень.
ypercubeᵀᴹ

Також додайте більше деталей. Чи буде запуск цього перетворювати всі таблиці в базу даних? Або весь сервер? Що буде, якщо таблиця не вдасться перетворити, і ми отримаємо помилку? Можливо, ми закінчимо кілька таблиць, перетворених, а деякі залишили в MyiSAM? Загалом, які ще речі слід розглянути DBA, перш ніж це запустити?
ypercubeᵀᴹ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.