Saya telah membahas ini di StackOverflow pada Oktober 2010 .
Ingatlah file tersibuk di infrastruktur InnoDB: / var / lib / mysql / ibdata1
File ini biasanya menampung empat jenis informasi
- Tabel Data
- Indeks Tabel
- Data MVCC (Multiversioning Concurrency Control)
- Table Metadata (Daftar ID tablespace)
Berlari OPTIMIZE TABLE
melawan tabel InnoDB yang disimpan di ibdata1 melakukan dua hal:
- Membuat data tabel dan indeks berdekatan di dalam ibdata1, sehingga lebih cepat diakses
- Itu membuat ibdata1 tumbuh karena data yang berdekatan dan halaman indeks ditambahkan ke ibdata1
Meskipun Anda dapat memisahkan Data Tabel dan Indeks Tabel dari ibdata1 dan mengelolanya secara independen menggunakan innodb_file_per_table , seluruh ruang disk yang besar di ibdata1 tidak akan hilang dan tidak dapat direklamasi. Anda harus berbuat lebih banyak.
Untuk menyusutkan ibdata1 sekali dan untuk semua Anda harus melakukan hal berikut:
1) MySQLDump semua database menjadi file teks SQL (sebut saja /root/SQLData.sql)
2) Jatuhkan semua basis data (kecuali skema mysql)
3) Matikan mysql
4) Tambahkan baris berikut ke /etc/my.cnf
[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G
Sidenote: Apa pun yang Anda atur untuk innodb_buffer_pool_size, pastikan innodb_log_file_size adalah 25% dari innodb_buffer_pool_size.
5) Hapus ibdata1, ib_logfile0 dan ib_logfile1
Pada titik ini, seharusnya hanya ada skema mysql di / var / lib / mysql
6) Mulai ulang mysql
Ini akan membuat ulang data ib di 10 atau 18MB (tergantung pada versi MySQL), ib_logfile0 dan ib_logfile1 masing-masing 1G
7) Muat ulang /root/SQLData.sql ke mysql
ibdata1 akan tumbuh tetapi hanya berisi tabel metadata. Bahkan, itu akan tumbuh sangat lambat selama bertahun-tahun. Satu-satunya cara pertumbuhan ibdata1 dengan cepat adalah jika Anda memiliki satu atau lebih hal berikut ini:
- Banyak DDL (
CREATE TABLE
, DROP TABLE
, ALTER TABLE
)
- Banyak transaksi
- Banyak perubahan untuk dilakukan per transaksi
Setiap tabel InnoDB akan ada di luar ibdata1
Misalkan Anda memiliki tabel InnoDB bernama mydb.mytable. Jika Anda masuk ke / var / lib / mysql / mydb, Anda akan melihat dua file yang mewakili tabel
- mytable.frm (Header Mesin Penyimpan)
- mytable.ibd (Rumah Tabel Data dan Indeks Tabel untuk mydb.mytable)
ibdata1 tidak akan pernah lagi memuat data dan Indeks InnoDB.
Dengan opsi innodb_file_per_table di /etc/my.cnf, Anda dapat menjalankan OPTIMIZE TABLE mydb.mytable;
dan file /var/lib/mysql/mydb/mytable.ibd akan menyusut.
Saya telah melakukan ini berkali-kali dalam karir saya sebagai DBA MySQL
Faktanya, pertama kali saya melakukan ini, saya menciutkan file ibdata1 50GB menjadi 500MB.
Cobalah. Jika Anda memiliki pertanyaan lebih lanjut tentang ini, email saya. Percayalah kepadaku. Ini akan bekerja dalam jangka pendek dan jangka panjang !!!
UPDATE 2012-04-19 09:23 EDT
Setelah menjalankan langkah-langkah di atas, bagaimana Anda bisa menentukan tabel apa yang perlu didefragmentasi? Dimungkinkan untuk mengetahuinya, tetapi Anda akan memiliki skripnya.
Berikut ini sebuah contoh: Misalkan Anda memiliki tabel mydb.mytable
. Dengan diaktifkan innodb_file_per_table, Anda memiliki file /var/lib/mysql/mydb/mytable.ibd
Anda harus mengambil dua angka
MEMASANG DARI OS: Anda dapat memastikan ukuran file dari OS seperti ini
ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'
FILESIZE DARI INFORMATION_SCHEMA: Anda dapat memastikan filesize dari information_schema.tabel seperti ini:
SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';
Cukup kurangi nilai INFORMATION_SCHEMA dari nilai OS dan bagilah selisihnya dengan nilai INFORMATION_SCHEMA.
Dari sana Anda akan memutuskan berapa persen yang dianggap perlu untuk men-defrag tabel itu. Tentu saja, Anda defrag menggunakan salah satu dari perintah berikut:
OPTIMIZE TABLE mydb.mytable;
atau
ALTER TABLE mydb.mytable ENGINE=InnoDB;