MySQL InnoDB не звільняє місце на диску після видалення рядків даних із таблиці


140

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

Чи є можливість повернути дисковий простір з MySQL?

Я в поганій ситуації; ця програма працює приблизно в 50 різних місцях, і тепер проблема малого місця на диску з’являється майже у всіх.


після запуску команди оптимізації також розмір файлу ibdata1 не зменшився.
Суміт Део

4
Я думаю, що цей коментар буде краще відредаговано у вашій відповіді, а потім видалено
Бен Міллвуд

можливий дублікат stackoverflow.com/q/11751792/82114 (але цей був тут першим)
FlipMcF

1
"Також не зменшився розмір файлу ibdata1 після запуску команди оптимізації таблиці" , тому що ваш innodb_file_per_tableвимкнено. Хороша новина полягає в тому, що ця опція onза замовчуванням є в останніх версіях MySQL.
Бухгалтер з

Я запустив "оптимізувати таблицю xxxx" і отримав повідомлення "Таблиця не підтримує оптимізацію, роблячи натомість відтворення + аналіз". Після запуску "du -h / var / lib / mysql" на оболонці я помітив, що база даних скоротилася.
користувач1097111

Відповіді:


137

MySQL не зменшує розмір ibdata1. Колись. Навіть якщо ви користуєтесьoptimize table звільняти простір, що використовується у видалених записах, він буде використовувати його повторно.

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


4
Документи MySQL 5.5 про стан режиму файлу за таблицею InnoDB "Щоб скористатись функціями [InnoDB file-per-table] для існуючої таблиці, ви можете увімкнути налаштування файлу на таблицю та запустити ALTER TABLE t ENGINE=INNODBв існуючій таблиці. " Це означає, що ви можете ввімкнути цю функцію, "перетворити" існуючі таблиці, щоб використовувати окремий файл InnoDB з командою ALTER TABLE, а потім ОПТИМІЗУВАТИ таблицю, щоб зменшити її розмір. Однак, як тільки ви закінчите, вам доведеться розібратися, як видалити (величезний) вихідний файл InnoDB ...
Josh

9
Я думаю, що це технічно відповідає на питання, але я би сподівався, що більшість людей, які шукають цю тему, шукають, щоб власне процес зменшив / повернув простір, чого ця відповідь не забезпечує.
Маначі

@Manachi Процес - "налаштувати сервер на використання innodb_file_per_table", "створити резервну копію" сервера, "скинути базу даних", зупинити mysql, видалити .ibd, запустити сервер і відновити базу даних. З MySQL 5.5+ ви можете використовувати те, що сказав Джош, і, змінивши всі таблиці, зупиніть сервер, видаліть величезний .ibd і запустіть його заново.
Леонель Мартінс

39

Просто у мене була така сама проблема.

Що відбувається, це те, що навіть якщо ви скинете базу даних, innodb все одно не звільнить місце на диску. Мені довелося експортувати, зупинити mysql, видалити файли вручну, запустити mysql, створити базу даних та користувачів, а потім імпортувати. Слава богу, у мене було лише рядків на суму 200 МБ, але це пощадило 250 ГБ файлу innodb.

Збій по дизайну.


10
так, це безумовно невдача.
trusktr

1
У MySql 5.5 є та сама проблема: я запустив "оптимізувати таблицю", щоб зменшити використання диска таблиці 28 ГБ. Операція, ймовірно, намагалася зробити оптимізований клон оригінального, і таким чином використовувала весь простір на розділі. Тепер "оптимізувати таблицю" не вдалося, і я не маю місця на розділі навіть після того, як я скинув весь db ... дуже невтішно.
basilikode

1
І через 4 роки я зіткнувся з тією ж проблемою з MySQL. MS SQL схожий: dba.stackexchange.com/questions/47310/…
Csaba Toth

24

Якщо ви не використовуєте innodb_file_per_table , повернення дискового простору можливе, але досить виснажливе і вимагає значного простою.

Як досить детальний - але я вставив відповідну частину нижче.

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

Наразі ви не можете видалити файл даних із системного простору таблиць. Щоб зменшити розмір простору системних таблиць, скористайтеся цією процедурою:

Використовуйте mysqldump для скидання всіх таблиць InnoDB.

Зупинити сервер.

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

Видаліть будь-які файли .frm для таблиць InnoDB.

Налаштування нового простору таблиць.

Перезавантажте сервер.

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


Дякуємо, що включили кроки - afaict, що посилання "як", більше не містить цієї інформації
aland

3

Через десять років у мене була та сама проблема. Я вирішив це таким чином:

  • Я оптимізував всі бази даних, що залишилися.
  • Я перезапустив комп'ютер і MySQL на сервісах (Windows + r -> services.msc)

Це все :)


1

Інший спосіб вирішити проблему з рекультивацією простору: Створіть декілька розділів всередині таблиці - на основі діапазону, розділів на основі значення та просто скиньте / обріжте розділ, щоб повернути простір, що звільнить простір, який використовується всіма даними, що зберігаються в конкретному розділі.

Коли ви вводите розділ для таблиці, будуть потрібні деякі зміни, як-от - унікальні ключі, індекси для включення стовпця розділів тощо.


0

Рік тому я також зіткнувся з тією ж проблемою у версії mysql5.7, і ibdata1 займав 150 Gb. тому я додав скасувати таблиці

Візьміть резервну копію Mysqldump
Зупинити службу mysql
Видалити всі дані з даних dir
Додати нижче параметр скасувати табличну область в поточному 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

Проблема вирішена !!


-1

Існує кілька способів відновити диск на диску після видалення даних з таблиці для двигуна MySQL Inodb

Якщо ви не використовуєте innodb_file_per_table з самого початку, скидання всіх даних, видалення всіх файлів, відновлення бази даних та імпорт даних знову є єдиним способом (перевірте відповіді FlipMcF вище)

Якщо ви використовуєте innodb_file_per_table, ви можете спробувати

  1. Якщо ви зможете видалити всі усічені дані, команда видалить дані та поверне диск для вас.
  2. Команда Alter table знизить і відтворить таблицю, щоб вона могла повернути диск. Тому після видалення даних запустіть таблицю alter, яка нічого не змінює, щоб звільнити жорсткий диск (тобто: таблиця TBL_A має charset 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 дуже погана продуктивність)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.