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

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

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

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

8 ответов


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

но вы можете настроить MySQL так, чтобы каждая таблица, включая ее индексы, хранилась как отдельный файл. Таким образом ibdata1 не будет расти, как большой. Согласно Билл Karwin комментарий это включено по умолчанию с версии 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. удалить все базы данных кроме вышеуказанных 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, это не обязательно и невозможно отбросить. На самом деле это просто куча представлений только для чтения, а не таблиц. И нет никаких файлов, связанных с ними, даже каталога базы данных. The informations_schema использует db-engine памяти и отбрасывается и регенерируется при остановке/перезапуске mysqld. См.https://dev.mysql.com/doc/refman/5.7/en/information-schema.html.


когда вы удаляете таблицы 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


добавлять к ответ Джона П,

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


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

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

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


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

MySQL > 5.1.24:

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

MySQL

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

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

du -b ibdata1

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


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

[mysqld]
innodb_file_per_table=1


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

быстро написал процедуру принятого ответа в 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 (и ).

предполагается, что у вас credendials администратор в /root/.my.cnf и что ваша база данных живет в умолчанию


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

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

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

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