Howto: Очистити движок зберігання даних mysql InnoDB?


133

Чи можна очистити движок зберігання даних mysql innodb, щоб він не зберігав дані з видалених таблиць?

Або мені потрібно кожного разу відновлювати нову базу даних?


Що змушує вас думати, що MySQL зберігає дані з видалених таблиць?
Роберт Мунтяну

1
Якщо я скидаю цілу купу величезних таблиць, мої файли пам’яті InnoDB не скорочуються
Bryan Field

2
@RobertMunteanu: див. Bugs.mysql.com/bug.php?id=1341
Макс

Відповіді:


351

Ось більш повна відповідь щодо InnoDB. Це трохи тривалий процес, але можна вартих зусиль.

Майте на увазі, що /var/lib/mysql/ibdata1це найзайнятіший файл в інфраструктурі InnoDB. Зазвичай вона містить шість типів інформації:

  • Дані таблиці
  • Табличні покажчики
  • Дані MVCC (мультиверсійний контроль за сумісністю)
    • Відхилення сегментів
    • Скасувати пробіл
  • Метадані таблиці (Словник даних)
  • Подвійний буфер запису (фонове записування для запобігання надійності кешування ОС)
  • Вставити буфер (керування змінами не унікальних вторинних індексів)
  • Дивіться Pictorial Representation of ibdata1

Архітектура InnoDB

Архітектура InnoDB

Багато людей створюють кілька ibdataфайлів, сподіваючись на краще управління дисковим простором та продуктивністю, однак ця думка помилкова.

Чи можна бігати OPTIMIZE TABLE?

На жаль, біг OPTIMIZE TABLEпроти таблиці InnoDB, що зберігається у спільному файлі простору таблиць, ibdata1робить дві речі:

  • Робить дані таблиці та індекси суміжними всередині ibdata1
  • Робить ibdata1рости , тому що суміжні сторінки даних і індексні додаються доibdata1

Однак можна відокремити дані таблиці та індекси таблиць від ibdata1них та самостійно керувати ними.

Можу чи я працювати OPTIMIZE TABLEз innodb_file_per_table?

Припустимо , що ви повинні були додати innodb_file_per_tableдо /etc/my.cnf (my.ini). Чи можете ви просто запустити OPTIMIZE TABLEвсі таблиці InnoDB?

Хороші новини : Коли ви запустите OPTIMIZE TABLEз innodb_file_per_tableувімкненим, це створить .ibdфайл для цієї таблиці. Наприклад, якщо у вас є таблиця з mydb.mytableданими даних /var/lib/mysql, вона створить наступне:

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

Повідомлення .ibdміститиме сторінки даних та сторінки покажчиків для цієї таблиці. Чудово.

Погані новини : Все, що ви зробили, - це витягнути Сторінки даних та Індексні сторінки mydb.mytableз проживання ibdata. Запис у словнику даних для кожної таблиці, в тому числі mydb.mytable, все ще залишається у словнику даних (Див. Зображення ibdata1 ). ВИ НЕ МОЖЕТЕ ПРОСТО ПРОБЛЕМАТИ ibdata1НА ЦЕЙ ТОЧКІ !!! Зверніть увагу, що ibdata1зовсім не скоротився.

Очищення інфраструктури InnoDB

Щоб стиснути ibdata1раз і назавжди, ви повинні зробити наступне:

  1. Скинути (наприклад, з mysqldump) всі бази даних у .sqlтекстовий файл ( SQLData.sqlвикористовується нижче)

  2. Відкиньте всі бази даних (крім mysqlі information_schema) CAVEAT : Для запобіжних заходів запустіть цей сценарій, щоб переконатися, що у вас є всі грантові користувачі:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Увійдіть до mysql та запустіть SET GLOBAL innodb_fast_shutdown = 0;(Це повністю змине всі зміни, що залишилися у трансакції від ib_logfile0та ib_logfile1)

  4. Вимкнення MySQL

  5. Додайте наступні рядки до /etc/my.cnf(або my.iniв Windows)

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G

    (Сторінка: Що б ви не встановили innodb_buffer_pool_size, переконайтеся, що innodb_log_file_sizeце 25% innodb_buffer_pool_size.

    Також: innodb_flush_method=O_DIRECTнедоступно для Windows)

  6. Видалити ibdata*і ib_logfile*, за бажанням, можна видалити всі папки /var/lib/mysql, крім них /var/lib/mysql/mysql.

  7. Запустіть MySQL (Це дозволить відтворити ibdata1[10 МБ за замовчуванням] ib_logfile0та ib_logfile1по 1G кожен).

  8. Імпорт SQLData.sql

Тепер ibdata1вони все ще будуть рости, але містять лише метадані таблиці, оскільки кожна таблиця InnoDB існуватиме поза межами ibdata1. ibdata1більше не буде містити дані InnoDB та індекси для інших таблиць.

Наприклад, припустимо, у вас є таблиця InnoDB mydb.mytable. Якщо ви заглянете /var/lib/mysql/mydb, ви побачите два файли, що представляють таблицю:

  • mytable.frm (Заголовок двигуна зберігання)
  • mytable.ibd (Дані таблиці та індекси)

З innodb_file_per_tableопцією в /etc/my.cnf, ви можете запустити OPTIMIZE TABLE mydb.mytableі файл /var/lib/mysql/mydb/mytable.ibdфактично скоротиться.

Я робив це багато разів у своїй кар’єрі як MySQL DBA. Насправді, коли я це зробив, я скоротив файл на 50 ГБ ibdata1 до всього 500 МБ!

Спробувати. Якщо у вас є додаткові запитання щодо цього, просто запитайте. Довірся мені; це буде працювати як в короткостроковій перспективі, так і в довгостроковій перспективі.

КАВАТИ

На кроці 6, якщо mysql не вдасться перезапустити через те, що mysqlсхема починає випадати, огляньтесь на крок 2. Ви зробили фізичну копію mysqlсхеми. Відновити його можна наступним чином:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Поверніться до кроку 6 і продовжуйте

ОНОВЛЕННЯ 2013-06-04 11:13 EDT

Що стосується встановлення innodb_log_file_size на 25% від innodb_buffer_pool_size на кроці 5, це правило для ковдр є досить старою школою.

Повернувшись July 03, 2006, у Percona була чудова стаття, чому вибрати правильний innodb_log_file_size . Згодом Nov 21, 2008Перкона переглянув ще одну статтю про те, як обчислити належний розмір, виходячи з пікового навантаження, зберігаючи зміни години .

З тих пір я писав повідомлення в DBA StackExchange про обчислення розміру журналу і де я посилався на ці дві статті Percona.

Особисто я все одно ходив би з правилом 25% для початкової установки. Потім, оскільки робоче навантаження можна більш точно визначити з часом у виробництві, ви могли змінити розмір журналів під час циклу технічного обслуговування за лічені хвилини.


9
Я також застосував параметр innodb_file_per_table з великим ефектом, маючи 200 баз даних із 200 таблицями на одному сервері, я зміг символізувати різницю баз даних на різних розділах, тому використовуючи більше IO буферів і шпинделів, які в іншому випадку були б доступні :)
Дейв Рікс

2
@SeanDowney BTW не забудьте підняти innodb_open_tablesпри необхідності. За замовчуванням - 300.
RolandoMySQLDBA

2
@ giorgio79 вам потрібно встановити об'ємну вставку на більшу величину. Це хороший момент. Я додам суть вашого запитання до своєї відповіді.
RolandoMySQLDBA

3
У 32-бітових системах значення 4Gb для innodb_buffer_pool_size не допускається. Mysql буде мовчки починати з вимкнення innodb, а відновлені таблиці будуть змінені на myisam. Використовуйте трохи менше значення, щоб виправити це.
Девід

5
Добрий Бог. Я просто хочу сказати, що це, мабуть, одна з найкращих відповідей, яку я коли-небудь бачив на чудовій роботі ТАК Чорт, сер. Допоміг мені вирішити проблему, коли я отримував ПОМИЛКУ 2013 (HY000) під час імпорту 154гб. Дякую за відмінну відповідь!
Джош Браун

4

Двигун InnoDB не зберігає видалені дані. Під час вставлення та видалення рядків невикористаний простір залишається виділеним у файлах зберігання InnoDB. З часом загальний простір не зменшиться, але з часом «видалений і звільнений» простір буде автоматично використаний сервером БД.

Ви можете додатково настроїти та керувати простором, який використовує двигун, за допомогою ручного повторного використання таблиць. Для цього потрібно скинути дані в уражені таблиці за допомогою mysqldump, скинути таблиці, перезапустити службу mysql, а потім відтворити таблиці з файлів дампа.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.