Я обратился к этому в StackOverflow еще в октябре 2010 года .
Помните о самом загруженном файле в инфраструктуре InnoDB: / var / lib / mysql / ibdata1
Этот файл обычно содержит четыре типа информации
- Данные таблицы
- Табличные индексы
- Данные MVCC (Multiversioning Concurrency Control)
- Метаданные таблицы (список идентификаторов табличного пространства)
Запуск OPTIMIZE TABLE
таблицы InnoDB, хранящейся в ibdata1, делает две вещи:
- Делает данные таблицы и индексы смежными внутри ibdata1, таким образом, более быстрый доступ
- Это делает ibdata1 растущим, потому что смежные страницы данных и индексов добавляются к ibdata1
Хотя вы можете отделить Табличные данные и Табличные индексы от ibdata1 и управлять ими независимо, используя innodb_file_per_table , большое свободное пространство на диске в ibdata1 просто не исчезнет и не может быть восстановлено. Вы должны сделать больше.
Чтобы сжать ibdata1 раз и навсегда, вы должны сделать следующее:
1) MySQLDump все базы данных в текстовый файл SQL (назовите его /root/SQLData.sql)
2) Удалить все базы данных (кроме схемы mysql).
3) Отключение mysql
4) Добавьте следующие строки в /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.
5) Удалить ibdata1, ib_logfile0 и ib_logfile1
На этом этапе должна быть только схема mysql в / var / lib / mysql
6) Перезапустите MySQL
Это воссоздает ibdata1 на 10 или 18 МБ (в зависимости от версии MySQL), ib_logfile0 и ib_logfile1 на 1G каждый
7) Перезагрузите /root/SQLData.sql в mysql
ibdata1 будет расти, но будет содержать только метаданные таблицы. На самом деле, он будет расти очень медленно с годами. Единственный способ быстрого роста ibdata1 - это если у вас есть одно или несколько из следующих:
- Много DDL (
CREATE TABLE
, DROP TABLE
, ALTER TABLE
)
- Много транзакций
- Много изменений для фиксации за транзакцию
Каждая таблица 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 МБ.
Попробуйте. Если у вас есть дополнительные вопросы по этому поводу, напишите мне. Доверьтесь мне. Это будет работать в краткосрочной и долгосрочной перспективе !!!
ОБНОВЛЕНИЕ 2012-04-19 09:23 ПО ВОСТОЧНОМУ ВРЕМЕНИ
После выполнения описанных выше шагов, как вы можете определить, какие таблицы необходимо дефрагментировать? Это можно выяснить, но у вас будет скрипт.
Вот пример: Предположим, у вас есть таблица mydb.mytable
. С включенной innodb_file_per_table у вас есть файл /var/lib/mysql/mydb/mytable.ibd
Вам нужно будет получить два номера
ФАЙЛИЗАЦИЯ ИЗ ОС: Вы можете определить размер файла из ОС, как это
ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'
FILESIZE FROM INFORMATION_SCHEMA: Вы можете определить размер файла из файла information_schema.tables следующим образом:
SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';
Просто вычтите значение INFORMATION_SCHEMA из значения ОС и разделите разницу на значение INFORMATION_SCHEMA.
Оттуда вы решите, какой процент считает необходимым дефрагментировать эту таблицу. Конечно, вы дефрагментируете его с помощью одной из следующих команд:
OPTIMIZE TABLE mydb.mytable;
или
ALTER TABLE mydb.mytable ENGINE=InnoDB;