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

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

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

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


person Sumit Deo    schedule 13.08.2009    source источник
comment
после запуска команды optimize размер файла ibdata1 не уменьшился.   -  person Sumit Deo    schedule 13.08.2009
comment
Я думаю, что этот комментарий лучше было бы отредактировать в вашем ответе, а затем удалить   -  person Ben Millwood    schedule 24.09.2012
comment
возможный дубликат stackoverflow.com/q/11751792/82114 (но этот был здесь первым)   -  person FlipMcF    schedule 05.09.2013
comment
Размер файла ibdata1 не уменьшился после выполнения команды оптимизации таблицы, потому что ваш _ 1_ отключен. Хорошая новость в том, что в последних версиях MySQL эта опция по умолчанию on.   -  person Accountant م    schedule 17.08.2019
comment
Я запустил оптимизацию таблицы xxxx и получил сообщение Таблица не поддерживает оптимизацию, вместо этого выполняя воссоздание + анализ. После запуска du -h / var / lib / mysql в оболочке я увидел, что база данных уменьшилась.   -  person user1097111    schedule 10.07.2020


Ответы (9)


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

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

person Leonel Martins    schedule 14.08.2009
comment
Документация MySQL 5.5 о режиме "файл на таблицу" в InnoDB state Чтобы воспользоваться преимуществами функций [InnoDB file-per-table] для существующей таблицы, вы можете включить настройку file-per-table и запустить ALTER TABLE t ENGINE=INNODB для существующей таблицы. Это означает, что вы можете включить эту функцию, преобразовать существующие таблицы для использования отдельного файла InnoDB с помощью команды ALTER TABLE, а затем ОПТИМИЗИРОВАТЬ таблицу, чтобы уменьшить ее размер. Однако, как только вы закончите, вам нужно будет выяснить, как удалить (огромный) исходный файл InnoDB ... - person Josh; 28.10.2014
comment
Я предполагаю, что это технически отвечает на вопрос, но я ожидаю, что большинство людей, ищущих эту тему, ищут фактический процесс сокращения / освобождения пространства, которого этот ответ не предоставляет. - person Manachi; 12.02.2017
comment
@Manachi Процесс заключается в настройке сервера на использование innodb_file_per_table, резервном копировании сервера, удалении базы данных (ей), остановке mysql, удалении .ibd, запуске сервера и восстановлении базы данных (и). В MySQL 5.5+ вы можете использовать то, что сказал Джош, и после изменения всех таблиц остановить сервер, удалить огромный .ibd и запустить его снова. - person Leonel Martins; 14.02.2017

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

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

Неудачный проект.

person gilm    schedule 25.12.2009
comment
да, это определенно провал. - person trusktr; 04.11.2013
comment
MySql 5.5 имеет ту же проблему: я запустил оптимизацию таблицы, чтобы уменьшить использование диска для таблицы размером 28 ГБ. Операция, вероятно, пыталась создать оптимизированный клон исходного, и при этом израсходовалось все пространство на разделе. Теперь оптимизировать таблицу не удалось, и у меня не осталось места в разделе даже после того, как я сбросил всю базу данных ... очень разочаровывает. - person protoboolean; 20.04.2015
comment
И спустя 4+ года я столкнулся с той же проблемой с MySQL. MS SQL аналогичен: dba.stackexchange.com/ questions / 47310 / - person Csaba Toth; 05.05.2017

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

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

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

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

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

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

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

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

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

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

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

person FlipMcF    schedule 19.01.2012
comment
Спасибо за то, что вы добавили шаги - если ссылка "как сделать" больше не содержит этой информации. - person aland; 18.08.2015

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

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

Это все :)

person Matheus Douglas    schedule 13.08.2019
comment
Да, просто ОПТИМИЗИРУЙТЕ ТАБЛИЦУ tbl_name; и перезапуск mysql - person Vit; 17.09.2020

Разобрался с этой проблемой сегодня (через 11 лет после того, как вопрос был первоначально задан), и смог исправить ее, отбросив таблицу и создав ее снова. Мне не нужно было переустанавливать БД или дамп и восстановление, изменять хранилище, изменять таблицы и т. Д. - ничего из этого.

Я использую InnoDB, но не innodb_file_per_table, поэтому даже после того, как я удалил 900K строк из таблицы, размер БД не сдвинулся с места. Поэтому я отбросил таблицу и создал ее снова.

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

create table mynewtable as select * from myoldtable where 1=2;

С последующим

drop table myoldtable;

Это уменьшило размер моей БД с 5G до 400MB.

person SuhasM    schedule 12.03.2021
comment
Добро пожаловать в Stack Overflow. Природа баз данных такова, что данные не возвращаются в систему из-за удаленных записей. Судя по моему исследованию, INNODB не имеет команды восстановления ресурсов или аналогичной, как в некоторых базах данных. Однако в вашем случае у меня возникло бы искушение попробовать TRUNCATE TABLE myoldtable; ... Я полагаю, что это было бы более простым решением. - person Dennis; 12.03.2021
comment
Спасибо - про TRUNCATE забыл. Широко использовал его в Oracle, но не думал о том, чтобы попробовать его здесь. Запишу это для использования в будущем :) - person SuhasM; 07.04.2021
comment
TRUNCATE TABLE также не освобождает дисковое пространство в моем случае. - person XuDing; 23.07.2021

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

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

person Anand Immannavar    schedule 10.02.2015

Год назад я также столкнулся с той же проблемой на версии 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 и сохранить резервную копию mysqldump

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

person Gajendra    schedule 21.05.2020

Если ОПТИМИЗАЦИЯ не решает вашу проблему, попробуйте:

ALTER TABLE tbl_name ENGINE=INNODB, ALGORITHM=INPLACE, LOCK=NONE;

or

ALTER TABLE tbl_name FORCE, ALGORITHM=INPLACE, LOCK=NONE;
person Wellington1993    schedule 23.06.2021

Есть несколько способов освободить дисковое пространство после удаления данных из таблицы для 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 очень плохая производительность)
person Bùi Đức Khánh    schedule 25.04.2016
comment
Обратите внимание, что при выборе варианта 3 будут отброшены представления / индексы, построенные на основе TBL_A, что приведет к снижению производительности и потенциально нарушит работу приложений. Кроме того, если TBL_A является источником внешнего ключа, вы не сможете его удалить. Вариант 2 также следует применять с осторожностью, как под прикрытием. он делает то же самое, что и вариант 3. Не уверен, будут ли индексы / представления перестроены после ALTER (сомневаюсь). В целом, за исключением TRUNCATE, вышеупомянутые методы не являются бизнес-практиками, и, как минимум, они должны выполняться только в течение предписанного времени обслуживания и с особым вниманием к (супер- и суб-) зависимостям. - person Dennis; 12.04.2021
comment
Привет, @Dennis, вариант 3 - это то, что я узнал от Percona, в этом ответе я говорю только об идее сделать это, и на практике мне нужно обрабатывать все ограничения и бизнес с помощью логики кода, поэтому он не подходит для всех ситуаций. Еще одна вещь, это вопрос о том, как удалить данные и освободить диск. Я думаю, что все мои решения могут это сделать, но в каждом конкретном случае нам нужно выбрать то, что подходит. Иногда обрезать неиспользуемую большую таблицу журнала - это все, что вам нужно - person Bùi Đức Khánh; 25.04.2021