MySQL InnoDB не освобождает дисковое пространство после удаления строк данных из таблицы

142

У меня есть одна таблица MySQL, использующая механизм хранения InnoDB; он содержит около 2 млн строк данных. Когда я удалил строки данных из таблицы, выделенное дисковое пространство не освободилось. Размер файла ibdata1 не уменьшился после выполнения optimize tableкоманды.

Есть ли способ вернуть дисковое пространство из MySQL?

Я в плохой ситуации; это приложение запущено примерно в 50 различных местах, и теперь проблема нехватки места на диске возникает почти во всех из них.

Сумит Део
источник
после запуска команды optimize размер файла ibdata1 не уменьшился.
Sumit Deo
4
Я думаю, что этот комментарий лучше было бы отредактировать в вашем ответе, а затем удалить
Бен Миллвуд
возможный дубликат stackoverflow.com/q/11751792/82114 (но этот был здесь первым)
FlipMcF
1
«Размер файла ibdata1 не уменьшился после выполнения команды оптимизации таблицы» , потому что ваш innodb_file_per_tableвыключен. Хорошая новость в том, что onв последних версиях MySQL эта опция включена по умолчанию.
Бухгалтер م
Я запустил команду «оптимизировать таблицу xxxx» и получил сообщение «Таблица не поддерживает оптимизацию, вместо этого выполняю воссоздание + анализ». После запуска "du -h / var / lib / mysql" в оболочке я увидел, что база данных уменьшилась.
user1097111

Ответы:

141

MySQL не уменьшает размер ibdata1. Когда-либо. Даже если вы используете, optimize tableчтобы освободить пространство, используемое от удаленных записей, он будет повторно использовать его позже.

Альтернативой является настройка сервера для использования innodb_file_per_table, но для этого потребуется резервное копирование, удаление базы данных и восстановление. Положительным моментом является то, что файл .ibd для таблицы уменьшается после расширения optimize table.

Леонель Мартинс
источник
4
Документация MySQL 5.5 о состоянии режима InnoDB file-per-table «Чтобы воспользоваться преимуществами функций [InnoDB file-per-table] для существующей таблицы, вы можете включить настройку file-per-table и запустить ALTER TABLE t ENGINE=INNODBна существующей таблице. " Это означает, что вы можете включить эту функцию, «преобразовать» существующие таблицы для использования отдельного файла InnoDB с помощью команды ALTER TABLE, а затем ОПТИМИЗИРОВАТЬ таблицу, чтобы уменьшить ее размер. Однако, как только вы закончите, вам нужно будет выяснить, как удалить (огромный) исходный файл InnoDB ...
Джош
9
Я предполагаю, что это технически отвечает на вопрос, но я ожидаю, что большинство людей, ищущих эту тему, ищут фактический процесс сокращения / освобождения пространства, которого этот ответ не предоставляет.
Manachi
@Manachi Процесс: «настроить сервер для использования innodb_file_per_table», «создать резервную копию» сервера, «удалить базу данных (и)», остановить mysql, удалить .ibd, запустить сервер и восстановить базу (и). С MySQL 5.5+ вы можете использовать то, что сказал Джош, и после изменения всех таблиц остановить сервер, удалить огромный .ibd и запустить его снова.
Леонель Мартинс
40

У меня была такая же проблема.

Что происходит, так это то, что даже если вы отбрасываете базу данных, innodb все равно не освобождает дисковое пространство. Мне пришлось экспортировать, остановить mysql, удалить файлы вручную, запустить mysql, создать базу данных и пользователей, а затем импортировать. Слава богу, у меня было только 200 МБ строк, но это сэкономило 250 ГБ файла innodb.

Неудача по замыслу.

гильм
источник
10
да, это определенно провал.
trusktr 04
1
MySql 5.5 имеет ту же проблему: я запускал «оптимизацию таблицы», чтобы уменьшить использование диска для таблицы размером 28 ГБ. Операция, вероятно, пыталась создать оптимизированный клон исходного, и при этом израсходовалось все пространство на разделе. Теперь "оптимизировать таблицу" не удалось, и у меня не осталось места в разделе даже после того, как я сбросил всю базу данных ... очень разочаровывает.
protoboolean
1
И спустя 4+ года я столкнулся с той же проблемой с MySQL. MS SQL аналогичен: dba.stackexchange.com/questions/47310/…
Csaba Toth
25

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

« Как сделать» довольно подробно, но я вставил соответствующую часть ниже.

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

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

Используйте mysqldump для сброса всех ваших таблиц InnoDB.

Остановите сервер.

Удалите все существующие файлы табличных пространств, включая файлы ibdata и ib_log. Если вы хотите сохранить резервную копию информации, скопируйте все файлы ib * в другое место перед удалением файлов в вашей установке MySQL.

Удалите все файлы .frm для таблиц InnoDB.

Настройте новое табличное пространство.

Перезагрузите сервер.

Импортируйте файлы дампа.

FlipMcF
источник
1
Спасибо за то, что вы добавили шаги - аффикт, ссылка «как сделать» больше не содержит этой информации
aland
5

Десять лет спустя и у меня была такая же проблема. Я решил это следующим образом:

  • Оптимизировал, все базы остались.
  • Я перезапустил свой компьютер и MySQL в службах (Windows + r -> services.msc)

Это все :)

Матеус Дуглас
источник
1
Да, просто «ОПТИМИЗИРОВАТЬ ТАБЛИЦУ tbl_name;» и перезапуск mysql
Vit
1

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

Когда вы введете разделение для своей таблицы, потребуются некоторые изменения в схеме таблицы, например - Уникальные ключи, индексы для включения столбца раздела и т. Д.

Ананд Имманнавар
источник
0

Год назад я также столкнулся с той же проблемой в версии mysql5.7, а ibdata1 занимал 150 ГБ. поэтому я добавил табличные пространства отмены

Сделать резервную копию Mysqldump
Остановить службу mysql
Удалить все данные из каталога данных
Добавить ниже параметр отмены табличного пространства в текущем my.cnf

 #undo tablespace
  innodb_undo_directory =  /var/lib/mysql/
  innodb_rollback_segments = 128 
  innodb_undo_tablespaces = 3
  innodb_undo_logs = 128  
  innodb_max_undo_log_size=1G
  innodb_undo_log_truncate = ON

Запустить mysql service
store mysqldump backup

Проблема решена !!

Гаджендра
источник
-1

Есть несколько способов освободить дисковое пространство после удаления данных из таблицы для MySQL Inodb Engine.

Если вы не используете innodb_file_per_table с самого начала, выгрузка всех данных, удаление всех файлов, воссоздание базы данных и повторный импорт данных - единственный способ (проверьте ответы FlipMcF выше)

Если вы используете innodb_file_per_table, вы можете попробовать

  1. Если вы можете удалить все данные, команда truncate удалит данные и освободит дисковое пространство за вас.
  2. Команда Alter table удалит и воссоздает таблицу, чтобы освободить дисковое пространство. Поэтому после удаления данных запустите команду alter table, которая ничего не меняет, чтобы освободить жесткий диск (например: таблица TBL_A имеет кодировку uf8, после удаления данных запустите ALTER TABLE TBL_A charset utf8 -> эта команда ничего не меняет в вашей таблице, но она заставляет mysql воссоздать вашу таблицу и восстановить дисковое пространство
  3. Создайте TBL_B как TBL_A. Вставьте выбранные данные, которые вы хотите сохранить, из TBL_A в TBL_B. Отбросьте TBL_A и переименуйте TBL_B в TBL_A. Этот способ очень эффективен, если TBL_A и данные, которые необходимо удалить, большие (команда удаления в MySQL innodb очень низкая производительность)
Bùi Đức Khanh
источник