MySql - изменение innodb_file_per_table для живой базы данных

18

У меня есть большая БД MySql (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) MySQLDump все базы данных в текстовый файл 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

Фактически, в первый раз, когда я сделал это, я свернул файл 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;

Это создаст один файл, сохраняющий исходную структуру файла.

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

Вы можете сделать это для каждой таблицы InnoDB. К сожалению, ibdata1 останется 150 ГБ.

RolandoMySQLDBA
источник
во время запуска перезагрузки из .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; 

Проблема здесь в том, что для больших табличных пространств потребуется некоторое время.

Я бы посоветовал установить подчиненное устройство вашей живой базы данных, запустить преобразование на ведомом устройстве, затем либо отключить мастер / подчиненное устройство и скопировать новое пространство данных на ведущее устройство, либо назначить подчиненное устройство ведущим, как только оно догонит его. ,

Вам будет трудно сделать это изменение без простоев вообще.

Дерек Дауни
источник
+1 за грубость и честность, сказав «сократите свои потери». Вы могли бы также сказать «кусать пулю».
RolandoMySQLDBA
Вы можете использовать pt-online-schema-change, чтобы избежать простоев при запуске таблицы alter.
угловой комментарий