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

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

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

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

Ответ 1

То, что 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, вам действительно нужно удалить файл:

  • Сделайте mysqldump всех баз данных, процедур, триггеров и т.д. , за исключением mysql и performance_schema баз данных
  • Отбросить все базы данных , кроме указанных выше двух баз данных
  • Остановить mysql
  • Удалить ibdata1 и ib_log файлы
  • Запустить mysql
  • Восстановление из дампа

Когда вы запустите 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-движок памяти, и его отбрасывают и регенерируют после остановки/перезапуска mysqld. См. https://dev.mysql.com/doc/refman/5.7/en/information-schema.html.

Ответ 2

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

Для системы 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 изменены, чтобы охватить все базы данных, которые вы хотите сохранить.

Ответ 3

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

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

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

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

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

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

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

Ответ 4

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

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

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

Ответ 5

Быстро написал сценарий принятого ответа в 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;

Ответ 6

Если ваша цель - контролировать свободное пространство 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

Ответ 7

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

  • сбросить все ваши базы данных
  • удалить MySQL-сервер,
  • добавить в оставшийся my.cnf:
    [mysqld]
    innodb_file_per_table=1
  • стереть все в /var/lib/mysql
  • установить MySQL-сервер
  • восстановить пользователей и базы данных

Ответ 8

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

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

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

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