MySql - зміна innodb_file_per_table для живого DB


18

У мене є великий MySql DB (150 ГБ), і тільки зараз я помітив, що innodb_file_per_tableвстановлено встановлене значення, offзавдяки якому весь БД розміщується в одному файлі ( ibdata1). Я хочу активувати innodb_file_per_tableйого, щоб він заднім числом розділив БД на кілька файлів, який найкращий спосіб зробити це?

Відповіді:


32

Насправді існує лише один спосіб вирішити це. Вам доведеться експортувати дані за допомогою mysqldumps, скинути всі бази даних, вимкнути mysqld, видалити ib_logfile0, видалити ib_logfile1, видалити ibdata1, додати innodb_file_per_tableпід [mysqld]заголовком, запустити mysql.

Цю відповідь я опублікував у StackOverflow ще в жовтні 2010 року

Ось етапи, перелічені вертикально:

Крок 01) MySQLDзавантажте всі бази даних у текстовий файл SQL (назвіть його SQLData.sql)

Крок 02) Видаліть всі бази даних (крім схеми mysql)

Крок 03) Завершення роботи mysql

CAVEAT : Щоб повністю очистити незапущені транзакції з файлів InnoDB, запустіть це

mysql -uroot -p... -Ae"SET GLOBAL innodb_fast_shutdown = 0;"
service mysql stop

Крок 04) Додайте наступні рядки до /etc/my.cnf

[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.

Крок 05) Видаліть ibdata1, ib_logfile0 та ib_logfile1

На цьому етапі має бути лише схема mysql в / var / lib / mysql

Крок 06) Перезапустіть mysql

Це відтворить ibdata1 на 10 МБ, ib_logfile0 та ib_logfile1 на 1G кожен

Крок 07) Перезавантажте SQLData.sql в mysql

ibdata1 зростатиме, але містить лише метадані таблиці

Кожна таблиця InnoDB буде існувати поза ibdata1

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

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

ibdata1 більше ніколи не буде містити дані InnoDB та індекси.

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

Я робив це багато разів у своїй кар'єрі як MySQL DBA

Насправді, коли я це зробив, я згорнув файл ibdata1 об'ємом 50 ГБ на 500 Мб.

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

Існує альтернатива, яка витягне таблицю InnoDB, не зменшуючи ibdata1.

Крок 01) Додайте наступні рядки до /etc/my.cnf

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

Крок 02) service mysql restart

Крок 03) Щоб витягти єдину таблицю InnoDB під назвою mydb.mytable, виконайте це:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Це створить один файл pleus зберегти вихідний файл структури

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

Це можна зробити для кожної таблиці InnoDB. На жаль, ibdata1 залишиться 150 Гб.


під час запуску перезавантаження з .sql файлів я отримав наступну помилку ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesбудь-які ідеї?
Пробіг

@Ran, будь ласка, опублікуйте це як окреме запитання.
RolandoMySQLDBA


Якщо ви встановите, innodb_file_per_tableа потім виконайте виконання ALTER TABLEкожної окремої таблиці, чи можете ви видалити файл ibdata1, щоб повернути простір без необхідності відновлення?
SystemParadox

1
@SystemParadox АБСОЛЮТНО НЕ !!!!!!!! Ви втратите словник даних.
RolandoMySQLDBA

5

Якщо ви хочете повернути простір ibdata, скидання / відновлення - це ваш єдиний вибір, як вказує Роландо . Також, мабуть, найкраще для виконання цього зробити.

Однак, якщо ви просто хочете зменшити свої втрати і «втратити» ці 150 Гб на жорсткому диску, ви можете просто включити innodb_file_per_tableв my.cnf і перезапустити сервер.

Потім для кожної таблиці видайте:

ALTER TABLE x DISABLE KEYS;
ALTER TABLE x ENGINE=InnoDB;
ALTER TABLE x ENABLE KEYS; 

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

Що я б запропонував - це налаштувати раб вашого живого db, запустити конверсію на підлеглий, а потім вимкнути головний / підлеглий і скопіювати нове простір даних у ведучий, або сприяти тому, щоб раб був господарем, як тільки він наздогнав. .

У вас виникнуть труднощі із внесенням цих змін без простоїв.


+1 за те, що ви були жорстоко чесними і казали: "скоротіть свої втрати". Ви могли сказати і «кусайте кулю».
RolandoMySQLDBA

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