MySQL InnoDB, tablodan veri satırlarını sildikten sonra disk alanını serbest bırakmıyor


140

InnoDB depolama motorunu kullanarak bir MySQL tablo var; yaklaşık 2M veri satırı içerir. Veri satırlarını tablodan sildiğimde, ayrılmış disk alanı serbest bırakmadı. optimize tableKomutu çalıştırdıktan sonra ibdata1 dosyasının boyutu da azalmadı .

MySQL'den disk alanı geri almanın bir yolu var mı?

Kötü bir durumdayım; Bu uygulama yaklaşık 50 farklı yerde çalışıyor ve şimdi neredeyse hepsinde düşük disk alanı sorunu ortaya çıkıyor.


optimize komutunu çalıştırdıktan sonra ibdata1 dosyasının boyutu azalmadı.
Sumit Deo

4
Bu yorumun cevabınızda daha iyi düzenleneceğini ve daha sonra silineceğini düşünüyorum
Ben Millwood

stackoverflow.com/q/11751792/82114 olası kopyası (ama bu ilk önce buradaydı)
FlipMcF

1
"Ne de ibdata1 dosyanın boyutu optimize tablo komutunu çalıştırdıktan sonra azaltmak vermedi" senin çünkü innodb_file_per_tablekapatılır. İyi haber şu ki, bu seçenek onvarsayılan olarak MySQL'in son sürümlerinde.
Muhasebeci م

Ben "tablo xxxx optimize" çalıştırın ve "Tablo optimizasyon desteklemiyor, bunun yerine rekreasyon + analiz yapıyor" mesajı aldım. Daha sonra bir kabuk üzerinde "du -h / var / lib / mysql" çalıştırarak, veritabanının küçüldüğünü görebiliyordum.
user1097111

Yanıtlar:


137

MySQL, ibdata1'in boyutunu azaltmaz. Hiç. optimize tableSilinen kayıtlardan kullanılan alanı boşaltmak için kullansanız bile , daha sonra tekrar kullanır.

Alternatif olarak sunucuyu kullanacak şekilde yapılandırmak mümkündür innodb_file_per_table, ancak bu bir yedekleme, bırakma veritabanı ve geri yükleme gerektirir. Olumlu tarafı, tablo için .ibd dosyasının bir optimize table.


4
MySQL 5.5 tablo başına dosya modu durumu hakkında " belge " Varolan bir tablo için [tablo başına dosya başına InnoDB] özelliklerinden yararlanmak için, tablo başına dosya ayarını açabilir ALTER TABLE t ENGINE=INNODBve varolan tablo üzerinde çalıştırabilirsiniz . " Bu, bu özelliği açabileceğiniz, ALTER TABLE komutuyla ayrı bir InnoDB dosyası kullanmak için varolan tabloları "dönüştürdüğünüz" ve ardından boyutunu küçültmek için tabloyu EN İYİ hale getirebileceğiniz anlamına gelir. Ancak, işiniz bittiğinde (büyük) kaynak InnoDB dosyasını nasıl sileceğinizi anlamanız gerekir ...
Josh

9
Sanırım bu teknik olarak soruyu cevaplıyor, ancak bu konuyu araştıran insanların çoğunun, bu cevabın sağlamadığı alanı küçültmek / geri kazanmak için gerçek süreci aramasını bekliyorum.
Manachi

@Manachi İşlem "sunucuyu innodb_file_per_table kullanacak şekilde yapılandır", "sunucuyu yedekle", "veritabanını bırak", mysql'i durdur, .ibd dosyasını sil, sunucuyu başlat ve veritabanlarını geri yükle. MySQL 5.5+ ile Josh'un söylediklerini kullanabilirsiniz ve tüm tabloları değiştirdikten sonra sunucuyu durdurun, büyük .ibd dosyasını silin ve yeniden başlatın.
Leonel Martins

39

Sadece aynı problemi kendim yaşadım.

Ne olur, veritabanını düşürseniz bile, innodb hala disk alanı serbest bırakmaz. Vermek, mysql durdurmak, dosyaları el ile kaldırmak, mysql başlatmak, veritabanı ve kullanıcılar oluşturmak ve sonra almak zorunda kaldı. Şükür sadece 200MB değerinde satır vardı, ama 250GB innodb dosyasını bağışladı.

Tasarım başarısız.


10
evet, bu kesinlikle bir başarısızlık.
trusktr

1
MySql 5.5 aynı sorunu var: Ben 28GB tablo disk kullanımını azaltmak için "tablo optimize" koştu. Operasyon muhtemelen orijinalin optimize edilmiş bir klonunu yapmaya çalıştı ve bunu bölümdeki tüm alanı kullandı. Şimdi "optimize masa" başarısız oldu ve ben bile tüm db düştükten sonra bölümü üzerinde boşluk bıraktım ... çok hayal kırıklığı.
basilikode

1
Ve 4+ yıl sonra MySQL ile aynı problemle karşılaştım. MS SQL benzerdir: dba.stackexchange.com/questions/47310/…
Csaba Toth

24

Kullanmak yoksa innodb_file_per_table , disk alanı ıslah mümkün, ama oldukça sıkıcı ve kesinti önemli miktarda gerektirir.

Nasıl tatlı derinlemesine - ama aşağıdaki ilgili kısmını yapıştırılan.

Ayrıca şemanızın bir kopyasını dökümünüzde tuttuğunuzdan emin olun.

Şu anda, sistem tablo alanından bir veri dosyasını kaldıramazsınız. Sistem tablo alanı boyutunu azaltmak için bu yordamı kullanın:

Tüm InnoDB tablolarınızı dökmek için mysqldump kullanın.

Sunucuyu durdurun.

İbdata ve ib_log dosyaları da dahil olmak üzere varolan tüm tablo alanı dosyalarını kaldırın. Bilgilerin yedek bir kopyasını saklamak istiyorsanız, MySQL kurulumunuzdaki dosyaları kaldırmadan önce tüm ib * dosyalarını başka bir konuma kopyalayın.

InnoDB tabloları için tüm .frm dosyalarını kaldırın.

Yeni bir tablo alanı yapılandırın.

Sunucuyu yeniden başlatın.

Döküm dosyalarını içe aktarın.


1
Adımları eklediğiniz için teşekkür ederiz - 'nasıl yapılır' bağlantısı artık bu bilgileri içermiyor
aland

3

On yıl sonra da aynı sorunu yaşadım. Bunu şu şekilde çözdüm:

  • Kalan tüm veritabanlarını optimize ettim.
  • Bilgisayarımı ve MySQL'i hizmetlerde yeniden başlattım (Windows + r -> services.msc)

Hepsi bu :)


1

Alan geri kazanımı sorununu çözmenin diğer bir yolu, tablo içinde birden çok bölüm oluşturmaktır - Aralık tabanlı, Değer tabanlı bölümler ve alanı geri almak için bölümü düşürmek / kısaltmaktır, bu da belirli bölümde depolanan tüm veriler tarafından kullanılan alanı serbest bırakır.

Tablonuz için bölümlemeyi tanıtırken tablo şemasında bazı değişiklikler olacaktır - Benzersiz Anahtarlar, bölüm sütununu içeren Dizinler vb.


0

Yıl önce ben de aynı sorunla karşı karşıya mysql5.7 sürümü ve ibdata1 150 Gb işgal etti. bu yüzden tabloları geri almayı ekledim

Mysqldump yedek al
mysql hizmetini durdur
Veri dizinindeki tüm verileri kaldır
Geçerli my.cnf dosyasında tablo alanı parametresini geri al

 #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 servis
deposu mysqldump yedeklemeyi başlat

Sorun çözüldü !!


-1

MySQL Inodb motoru için tablodan veri sildikten sonra disk alanını geri almanın birkaç yolu vardır

En baştan innodb_file_per_table kullanmıyorsanız, tüm verileri boşaltma, tüm dosyaları silme, veritabanını yeniden oluşturma ve verileri içe aktarma tek yoldur (yukarıdaki FlipMcF yanıtlarını kontrol edin)

İnnodb_file_per_table kullanıyorsanız, deneyebilirsiniz

  1. Tüm veri kesme komutunu silebilirseniz verileri siler ve disk alanını geri alır.
  2. Tablo değiştirme komutu, diskspace'i geri alabilmek için tabloyu bırakıp yeniden oluşturur. Bu nedenle, verileri sildikten sonra, hardisk'i serbest bırakmak için hiçbir şeyi değiştirmeyen alter tablosunu çalıştırın (yani: TBL_A tablosunda uf8 karakteri vardır, verileri sildikten sonra ALTER TABLE TBL_A charset utf8 -> bu komut tablonuzdan hiçbir şeyi değiştirmez, ancak mysql tablonuzu yeniden oluşturur ve yeniden kazanır disk alanı
  3. TBL_A gibi TBL_B oluşturun. TBL_A'dan saklamak istediğiniz belirli verileri TBL_B'ye ekleyin. TBL_A'yı bırakın ve TBL_B'yi TBL_A olarak yeniden adlandırın. TBL_A ve silinmesi gereken veriler büyükse bu şekilde çok etkilidir (MySQL innodb içindeki delete komutu çok kötü performans)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.