it-roy-ru.com

Как сжать / очистить файл ibdata1 в MySQL

Я использую MySQL в localhost в качестве "инструмента запросов" для выполнения статистики в R, то есть каждый раз, когда я запускаю скрипт R, я создаю новую базу данных (A), создаю новую таблицу (B), импортирую данные в B , отправьте запрос, чтобы получить то, что мне нужно, а затем я опускаю B и отбрасываю A.

Это нормально работает для меня, но я понимаю, что размер файла ibdata быстро увеличивается, я ничего не хранил в MySQL, но файл ibdata1 уже превысил 100 МБ.

Я использую более или менее настройку MySQL по умолчанию для установки, есть ли способ, которым я могу автоматически сжимать/очищать файл ibdata1 через фиксированный период времени?

533
lokheart

То, что ibdata1 не сжимается, является особенно раздражающей особенностью MySQL. Файл ibdata1 не может быть сокращен, если вы не удалите все базы данных, не удалите файлы и не перезагрузите дамп.

Но вы можете настроить MySQL так, чтобы каждая таблица, включая ее индексы, сохранялась как отдельный файл. Таким образом, ibdata1 не будет увеличиваться в размере. Согласно комментарий Билла Карвина это включено по умолчанию в версии 5.6.6 MySQL.

Это было некоторое время назад, я сделал это. Однако, чтобы настроить сервер на использование отдельных файлов для каждой таблицы, вам нужно изменить my.cnf, чтобы включить это:

[mysqld]
innodb_file_per_table=1

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

Так как вы хотите освободить место из ibdata1, вам действительно нужно удалить файл:

  1. Выполните mysqldump для всех баз данных, процедур, триггеров и т.д. , кроме баз данных mysql и performance_schema
  2. Удалите все базы данных , кроме двух указанных выше
  3. Стоп MySQL
  4. Удалить файлы ibdata1 и ib_log
  5. Запустите MySQL
  6. Восстановить из дампа

При запуске MySQL на шаге 5 файлы ibdata1 и ib_log будут воссозданы.

Теперь вы готовы идти. Когда вы создаете новую базу данных для анализа, таблицы будут располагаться в отдельных файлах ibd*, а не в ibdata1. Поскольку вы обычно удаляете базу данных вскоре после этого, файлы ibd* будут удалены.

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

Вы, наверное, видели это:
http://bugs.mysql.com/bug.php?id=1341

Используя команду ALTER TABLE <tablename> ENGINE=innodb или OPTIMIZE TABLE <tablename>, можно извлечь данные и проиндексировать страницы из ibdata1 в отдельные файлы. Однако ibdata1 не будет уменьшаться, если вы не выполните описанные выше шаги.

Что касается information_schema, это не нужно и не возможно отбросить. На самом деле это просто набор представлений только для чтения, а не таблиц. И нет никаких файлов, связанных с ними, даже каталог базы данных. informations_schema использует память db-engine и удаляется и восстанавливается при остановке/перезапуске mysqld. Смотрите https://dev.mysql.com/doc/refman/5.7/ru/information-schema.html .

750
John P

Добавление к ответ Джона П ,

Для системы linux шаги 1-6 могут быть выполнены с этими командами:

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. Sudo /etc/init.d/mysqld stop
  4. Sudo rm /var/lib/mysql/ibdata1
    Sudo rm /var/lib/mysql/ib_logfile (и удалите любые другие ib_logfile, которые могут быть названы ib_logfile0, ib_logfile1 и т. д ...)
  5. Sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql

Предупреждение: эти инструкции приведут к потере других баз данных, если у вас есть другие базы данных в этом экземпляре mysql. Убедитесь, что шаги 1,2 и 6,7 изменены, чтобы охватить все базы данных, которые вы хотите сохранить.

42
Vinay Vemula

Когда вы удаляете таблицы innodb, MySQL не освобождает пространство внутри файла ibdata, поэтому продолжает расти. Эти файлы почти не уменьшаются.

Как сжать существующий файл ibdata:

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

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

Если вы используете опцию конфигурации innodb_file_per_table, вы создаете несколько табличных пространств. То есть MySQL создает отдельные файлы для каждой таблицы вместо одного общего файла. Эти отдельные файлы хранятся в каталоге базы данных, и они удаляются при удалении этой базы данных. Это должно устранить необходимость сокращения/очистки файлов ibdata в вашем случае.

Дополнительная информация о нескольких табличных пространствах:

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

33
titanoboa

Если вы используете механизм хранения InnoDB для (некоторых) таблиц MySQL, вы, вероятно, уже столкнулись с проблемой его конфигурации по умолчанию. Как вы, возможно, заметили, в каталоге данных вашего MySQL (в Debian/Ubuntu -/var/lib/mysql) находится файл с именем ‘ibdata1 ′. Он содержит почти все данные InnoDB (это не журнал транзакций) экземпляра MySQL и может быть довольно большим. По умолчанию этот файл имеет начальный размер 10 МБ и автоматически расширяется. К сожалению, файлы данных InnoDB не могут быть сжаты. Вот почему DELETEs, TRUNCATEs, DROPs и т.д. Не освобождают пространство, используемое файлом.

Я думаю, что вы можете найти хорошее объяснение и решение там:

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/

14
Vik

Быстро запишем процедуру принятого ответа в bash:

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

Сохранить как purge_binlogs.sh и запустить как root.

Исключает mysql, information_schema, performance_schema (и каталог binlog).

Предполагается, что у вас есть учетные данные администратора в /root/.my.cnf и ваша база данных находится в каталоге /var/lib/mysql по умолчанию.

Вы также можете очистить двоичные журналы после запуска этого сценария, чтобы восстановить больше места на диске с помощью:

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;
7
Pierre-Alexis de Solminihac

Если ваша цель - следить за свободным пространством MySQL, и вы не можете остановить MySQL для сокращения файла ibdata, то получите его с помощью команд состояния таблицы. Пример:

MySQL> 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL <5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

Затем сравните это значение с вашим файлом ibdata:

du -b ibdata1

Источник: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html

6
Cyno

В новой версии mysql-сервера приведенные выше рецепты сокрушат базу "mysql". В старой версии это работает. В некоторых новых таблицах переключается на тип таблицы INNODB, и таким образом вы повредите их. Самый простой способ - сбросить все ваши базы данных, удалить mysql-сервер, добавить в оставшийся my.cnf:

[mysqld]
innodb_file_per_table=1


erase all in /var/lib/mysql
install mysql-server
restore users and databases
4
adjustable_wrench

Как уже отмечалось, вы не можете сжать ibdata1 (для этого вам нужно сделать дамп и перестроить), но в этом также нет особой необходимости.

Используя автоэкстенд (вероятно, самый распространенный параметр размера), ibdata1 предварительно выделяет хранилище, увеличиваясь при каждом его заполнении. Это делает запись быстрее, так как пространство уже выделено.

Когда вы удаляете данные, они не уменьшаются, но пространство внутри файла помечается как неиспользуемое. Теперь, когда вы вставляете новые данные, они будут повторно использовать пустое пространство в файле перед дальнейшим расширением файла.

Так что он будет только расти, если вам действительно нужны эти данные. Если вам не нужно пространство для другого приложения, вероятно, нет причин его уменьшать.

0
steveayre