Как: очистить механизм хранения MySQL InnoDB?

133

Можно ли очистить механизм хранения mysql innodb, чтобы он не сохранял данные из удаленных таблиц?

Или мне нужно каждый раз перестраивать новую базу данных?

Брайан Филд
источник
Что заставляет вас думать, что MySQL хранит данные из удаленных таблиц?
Роберт Мунтяну
1
Если я уроню целую кучу огромных таблиц, мои файлы хранилища InnoDB не уменьшатся,
Брайан Филд,
2
@RobertMunteanu: см. Bugs.mysql.com/bug.php?id=1341
Макс,

Ответы:

351

Вот более полный ответ относительно InnoDB. Это немного длительный процесс, но может стоить усилий.

Имейте в виду, что /var/lib/mysql/ibdata1это самый загруженный файл в инфраструктуре InnoDB. Обычно он содержит шесть типов информации:

  • Данные таблицы
  • Индексы таблиц
  • Данные MVCC (Multiversioning Concurrency Control)
    • Откат сегментов
    • Отменить пробел
  • Метаданные таблицы (словарь данных)
  • Double Write Buffer (фоновая запись для предотвращения зависимости от кэширования ОС)
  • Вставить буфер (управление изменениями неуникальных вторичных индексов)
  • Увидеть Pictorial Representation of ibdata1

InnoDB Архитектура

InnoDB Архитектура

Многие люди создают несколько ibdataфайлов в надежде на лучшее управление дисковым пространством и производительность, однако это мнение ошибочно.

Могу ли я бежать OPTIMIZE TABLE?

К сожалению, работа OPTIMIZE TABLEс таблицей InnoDB, хранящейся в файле общего табличного пространства, ibdata1делает две вещи:

  • Делает данные таблицы и индексы смежными внутри ibdata1
  • Растет, ibdata1потому что смежные страницы данных и индекса добавляются кibdata1

Однако вы можете отделить данные таблицы и индексы таблиц ibdata1и управлять ими независимо.

Могу ли я работать OPTIMIZE TABLEс innodb_file_per_table?

Предположим , что вы должны были добавить innodb_file_per_tableк /etc/my.cnf (my.ini). Можете ли вы тогда просто запустить OPTIMIZE TABLEвсе таблицы InnoDB?

Хорошие новости : когда вы запускаете OPTIMIZE TABLEс innodb_file_per_tableвключенным, это создаст .ibdфайл для этой таблицы. Например, если у вас есть таблица mydb.mytableс datadir of /var/lib/mysql, она выдаст следующее:

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

.ibdБудет содержать страницы данных и индексные страницы для этой таблицы. Отлично.

Плохие новости : все, что вы сделали, это извлекли страницы данных и индексные страницы mydb.mytableиз жизни ibdata. Запись словаря данных для каждой таблицы, включая mydb.mytable, по-прежнему остается в словаре данных (см. Графическое представление ibdata1 ). ВЫ НЕ МОЖЕТЕ ПРОСТО УДАЛИТЬ ibdata1НА ЭТОМ МЕСТЕ !!! Пожалуйста, обратите внимание, что ibdata1не сократился вообще.

Очистка инфраструктуры InnoDB

Чтобы сжать ibdata1раз и навсегда, вы должны сделать следующее:

  1. Дамп (например, с помощью mysqldump) всех баз данных в .sqlтекстовый файл ( SQLData.sqlиспользуется ниже)

  2. Отбросьте все базы данных (кроме mysqlи information_schema) ПРЕДОСТЕРЕЖЕНИЕ : В качестве меры предосторожности запустите этот сценарий, чтобы убедиться, что у вас есть все пользовательские гранты:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Войдите в mysql и запустите SET GLOBAL innodb_fast_shutdown = 0;(это полностью очистит все оставшиеся транзакционные изменения из ib_logfile0и ib_logfile1)

  4. Отключение MySQL

  5. Добавьте следующие строки в /etc/my.cnf(или my.iniв Windows)

    [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.

    Также: innodb_flush_method=O_DIRECTнедоступно в Windows)

  6. Удалить ibdata*иib_logfile* , при желании, вы можете удалить все папки /var/lib/mysql, кроме /var/lib/mysql/mysql.

  7. Запустите MySQL (будет воссоздано ibdata1[10 МБ по умолчанию] иib_logfile0 и ib_logfile1при 1G каждый).

  8. Импортировать SQLData.sql

Сейчас, ibdata1 прежнему будет расти, но содержать только метаданные таблицы, потому что каждая таблица InnoDB будет существовать вне ibdata1. ibdata1больше не будет содержать данные InnoDB и индексы для других таблиц.

Например, предположим, что у вас есть таблица InnoDB с именем mydb.mytable. Если вы посмотрите в/var/lib/mysql/mydb , вы увидите два файла, представляющих таблицу:

  • mytable.frm (Заголовок механизма хранения)
  • mytable.ibd (Табличные данные и индексы)

Включив innodb_file_per_tableопцию /etc/my.cnf, вы можете запуститьOPTIMIZE TABLE mydb.mytable и файл /var/lib/mysql/mydb/mytable.ibdдействительно сократится.

Я делал это много раз за свою карьеру администратора баз данных MySQL. Фактически, в первый раз, когда я сделал это, я сжал 50 ГБ ibdata1 файл до 500 МБ!

Попробуйте. Если у вас есть дополнительные вопросы по этому поводу, просто задавайте их. Доверьтесь мне; это будет работать как в краткосрочной, так и в долгосрочной перспективе.

ПРЕДОСТЕРЕЖЕНИЕ

На шаге 6, если mysql не может перезапуститься из-за того, что mysqlсхема begin отброшена, вернитесь к шагу 2. Вы сделали физическую копию mysqlсхемы. Вы можете восстановить его следующим образом:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Вернитесь к шагу 6 и продолжайте

ОБНОВЛЕНИЕ 2013-06-04 11:13 EDT

Что касается установки innodb_log_file_size на 25% от innodb_buffer_pool_size на шаге 5, это правило бланка - довольно старая школа.

Вернемся к тому July 03, 2006, что у Percona была хорошая статья, зачем выбирать правильный innodb_log_file_size . Позже Nov 21, 2008Percona выпустила еще одну статью о том, как рассчитать правильный размер на основе пиковой нагрузки с сохранением изменений на один час .

С тех пор я написал сообщения в DBA StackExchange о вычислении размера журнала и где я ссылался на эти две статьи Percona.

Лично я по-прежнему придерживаюсь правила 25% для начальной настройки. Затем, поскольку рабочая нагрузка может быть более точно определена с течением времени в процессе производства, вы можете изменить размеры журналов во время цикла обслуживания за считанные минуты.

RolandoMySQLDBA
источник
9
Я также с большим эффектом использовал опцию innodb_file_per_table, имея 200 баз данных по 200 таблиц в каждой на одном сервере, я смог символьно связать базы данных различий на разные разделы, поэтому использовал больше буферов ввода-вывода и шпинделей, которые в противном случае были бы доступны :)
Дэйв Рикс,
2
@SeanDowney Кстати не забывайте поднять в innodb_open_tablesслучае необходимости. Значение по умолчанию - 300.
RolandoMySQLDBA
2
@ giorgio79, вам нужно установить большую массовую вставку. Это хороший момент. К своему ответу добавлю суть вашего вопроса.
RolandoMySQLDBA
3
В 32-битных системах значение в 4 Гб для innodb_buffer_pool_size не допускается. Mysql автоматически запустится с отключенным innodb, а восстановленные таблицы будут изменены на myisam. Используйте немного меньшее значение, чтобы исправить это.
Дэвид
5
Боже. Я просто хочу сказать, что это, пожалуй, один из лучших ответов, которые я когда-либо видел на ТАК чертовски хорошая работа, сэр. Помог мне найти решение моей проблемы, когда я получал ОШИБКУ 2013 (HY000) при импорте 154 г дБ. Спасибо за отличный ответ!
Джош Браун
4

Движок InnoDB не хранит удаленные данные. Когда вы вставляете и удаляете строки, неиспользуемое пространство остается выделенным в файлах хранилища InnoDB. Со временем общее пространство не уменьшится, но со временем «удаленное и освобожденное» пространство будет автоматически повторно использовано сервером БД.

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

bigjeff
источник