MySQL InnoDB tidak merilis ruang disk setelah menghapus baris data dari tabel

140

Saya punya satu tabel MySQL menggunakan mesin penyimpanan InnoDB; ini berisi sekitar 2M baris data. Ketika saya menghapus baris data dari tabel, itu tidak merilis ruang disk yang dialokasikan. Ukuran file ibdata1 juga tidak berkurang setelah menjalankan optimize tableperintah.

Apakah ada cara untuk mendapatkan kembali ruang disk dari MySQL?

Saya dalam situasi yang buruk; aplikasi ini berjalan di sekitar 50 lokasi yang berbeda dan sekarang masalah ruang disk yang rendah muncul di hampir semuanya.

Sumit Deo
sumber
setelah menjalankan perintah optimisasi juga, ukuran file ibdata1 tidak berkurang.
Sumit Deo
4
Saya pikir komentar itu akan lebih baik diedit ke jawaban Anda, dan kemudian dihapus
Ben Millwood
kemungkinan duplikat stackoverflow.com/q/11751792/82114 (tapi yang ini ada di sini lebih dulu)
FlipMcF
1
"Ukuran file ibdata1 juga tidak berkurang setelah menjalankan perintah tabel mengoptimalkan" itu karena Anda innodb_file_per_tabledimatikan. Kabar baiknya adalah bahwa opsi ini onsecara default di versi terbaru MySQL.
Akuntan
Saya menjalankan "optimalkan tabel xxxx" dan mendapat pesan "Tabel tidak mendukung optimalkan, lakukan membuat ulang + menganalisis saja." Setelah menjalankan "du-h / var / lib / mysql" pada sebuah shell, saya bisa melihat bahwa database telah menyusut.
user1097111

Jawaban:

137

MySQL tidak mengurangi ukuran ibdata1. Pernah. Bahkan jika Anda menggunakan optimize tableuntuk membebaskan ruang yang digunakan dari catatan yang dihapus, itu akan digunakan kembali nanti.

Alternatifnya adalah mengkonfigurasi server yang akan digunakan innodb_file_per_table, tetapi ini akan membutuhkan cadangan, letakkan basis data, dan pulihkan. Sisi positifnya adalah bahwa file .ibd untuk tabel berkurang setelah optimize table.

Leonel Martins
sumber
4
MySQL 5.5 docs tentang status mode file-per-tabel InnoDB "Untuk memanfaatkan fitur [file-per-tabel InnoDB] untuk tabel yang ada, Anda dapat mengaktifkan pengaturan file-per-tabel dan menjalankan ALTER TABLE t ENGINE=INNODBdi tabel yang ada. " Ini menyiratkan bahwa Anda dapat mengaktifkan fitur ini, "mengubah" tabel yang ada untuk menggunakan file InnoDB terpisah dengan perintah ALTER TABLE, kemudian MENGOPTIMASI tabel untuk memperkecil ukurannya. Namun, begitu Anda selesai, Anda harus mencari cara untuk menghapus file InnoDB sumber (besar) ...
Josh
9
Saya kira ini secara teknis menjawab pertanyaan, tetapi saya berharap mayoritas orang mencari topik ini mencari proses aktual untuk menyusut / merebut kembali ruang, yang tidak disediakan jawaban ini.
Manachi
@Manachi Prosesnya adalah "mengkonfigurasi server untuk menggunakan innodb_file_per_table", "backup" server, "drop database (s)", hentikan mysql, hapus .ibd, mulai server dan pulihkan database. Dengan MySQL 5.5+ Anda dapat menggunakan apa yang dikatakan Josh, dan setelah mengubah semua tabel, hentikan server, hapus besar .ibd dan mulai lagi.
Leonel Martins
39

Baru saja mengalami masalah yang sama.

Apa yang terjadi adalah, bahwa bahkan jika Anda menjatuhkan basis data, innodb masih tidak akan merilis ruang disk. Saya harus mengekspor, menghentikan mysql, menghapus file secara manual, memulai mysql, membuat database dan pengguna, dan kemudian mengimpor. Terima kasih Tuhan, aku hanya punya 200MB baris, tapi itu menyelamatkan 250GB file innodb.

Gagal karena desain.

gilm
sumber
10
ya, itu pasti gagal.
trusktr
1
MySql 5.5 memiliki masalah yang sama: Saya menjalankan "optimalkan tabel" untuk mengurangi penggunaan disk dari tabel 28GB. Operasi mungkin mencoba untuk membuat tiruan yang dioptimalkan dari yang asli, dan melakukan hal itu menghabiskan semua ruang pada partisi. Sekarang "optimalkan tabel" gagal dan saya tidak memiliki ruang di partisi bahkan setelah saya menjatuhkan seluruh db ... sangat mengecewakan.
basilikode
1
Dan 4+ tahun kemudian saya mengalami masalah yang sama dengan MySQL. MS SQL serupa: dba.stackexchange.com/questions/47310/…
Csaba Toth
24

Jika Anda tidak menggunakan innodb_file_per_table , reklamasi ruang disk adalah mungkin, tetapi cukup membosankan, dan membutuhkan banyak waktu henti.

The Cara ini cukup mendalam - tapi saya disisipkan bagian yang relevan di bawah ini.

Pastikan juga menyimpan salinan skema Anda di tempat sampah Anda.

Saat ini, Anda tidak dapat menghapus file data dari tablespace sistem. Untuk mengurangi ukuran tablespace sistem, gunakan prosedur ini:

Gunakan mysqldump untuk membuang semua tabel InnoDB Anda.

Hentikan server.

Hapus semua file tablespace yang ada, termasuk file ibdata dan ib_log. Jika Anda ingin menyimpan salinan cadangan informasi, salin semua file ib * ke lokasi lain sebelum menghapus file di instalasi MySQL Anda.

Hapus file .frm untuk tabel InnoDB.

Konfigurasikan tablespace baru.

Mulai ulang server.

Impor file dump.

FlipMcF
sumber
Terima kasih telah menyertakan langkah-langkah - mengaitkan tautan 'cara' tidak lagi berisi informasi ini
aland
3

Sepuluh tahun kemudian dan saya memiliki masalah yang sama. Saya memecahkannya dengan cara berikut:

  • Saya mengoptimalkan semua database tetap.
  • Saya me-restart komputer dan MySQL saya pada layanan (Windows + r -> services.msc)

Itu semuanya :)

Matheus Douglas
sumber
1

Cara lain untuk memecahkan masalah reklamasi ruang adalah, Buat beberapa partisi dalam tabel - Rentang berbasis, partisi berbasis Nilai dan cukup jatuhkan / potong partisi untuk merebut kembali ruang, yang akan melepaskan ruang yang digunakan oleh seluruh data yang disimpan dalam partisi tertentu.

Akan ada beberapa perubahan yang diperlukan dalam skema tabel ketika Anda memperkenalkan partisi untuk tabel Anda seperti - Tombol Unik, Indeks untuk memasukkan kolom partisi dll.

Anand Immannavar
sumber
0

Tahun lalu saya juga menghadapi masalah yang sama pada versi mysql5.7 dan ibdata1 menempati 150 Gb. jadi saya menambahkan batalkan tablespace

Ambil cadangan Mysqldump
Hentikan layanan mysql
Hapus semua data dari dir data
Tambahkan di bawah ini batalkan parameter tablespace di my.cnf saat ini

 #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

Mulai layanan mysql
menyimpan cadangan mysqldump

Masalah terpecahkan !!

Gajendra
sumber
-1

Ada beberapa cara untuk mendapatkan kembali diskspace setelah menghapus data dari tabel untuk mesin MySQL Inodb

Jika Anda tidak menggunakan innodb_file_per_table dari awal, membuang semua data, menghapus semua file, membuat ulang basis data dan mengimpor data lagi adalah satu-satunya cara (periksa jawaban dari FlipMcF di atas)

Jika Anda menggunakan innodb_file_per_table, Anda dapat mencoba

  1. Jika Anda dapat menghapus semua perintah data truncate akan menghapus data dan mengklaim kembali ruang disk untuk Anda.
  2. Perintah mengubah tabel akan menjatuhkan dan membuat ulang tabel sehingga dapat merebut kembali ruang disk. Oleh karena itu setelah menghapus data, jalankan alter tabel yang tidak mengubah apa pun untuk melepaskan hardisk (yaitu: tabel TBL_A memiliki charset uf8, setelah hapus data jalankan ALTER TABLE TBL_A charset utf8 -> perintah ini tidak mengubah apa pun dari tabel Anda tetapi itu membuat mysql membuat kembali tabel Anda dan mendapatkan kembali ruang disk
  3. Buat TBL_B seperti TBL_A. Masukkan data pilihan yang ingin Anda simpan dari TBL_A ke TBL_B. Jatuhkan TBL_A, dan ganti nama TBL_B menjadi TBL_A. Cara ini sangat efektif jika TBL_A dan data yang diperlukan untuk menghapus adalah besar (perintah delete di MySQL innodb kinerjanya sangat buruk)
Bùi Đức Khánh
sumber