MySql - mengubah innodb_file_per_table untuk live db

18

Saya memiliki DB MySql besar (150GB) dan hanya sekarang saya perhatikan bahwa innodb_file_per_tableset diatur ke offyang menyebabkan seluruh DB di-host pada satu file tunggal ( ibdata1). Saya ingin mengaktifkan innodb_file_per_tabledan membuatnya secara retroaktif membagi DB menjadi beberapa file, apa cara terbaik untuk melakukan ini?

Ran
sumber

Jawaban:

32

Sebenarnya hanya ada satu cara untuk melakukannya. Anda harus mengekspor data menggunakan mysqldumps, letakkan semua database, matikan mysqld, hapus ib_logfile0, hapus ib_logfile1, hapus ibdata1, tambahkan di innodb_file_per_tablebawah [mysqld]tajuk, mulai di bawah judul, mulai mysql.

Saya memposting jawaban ini di StackOverflow kembali pada Oktober 2010

Berikut langkah-langkah yang tercantum secara vertikal:

Langkah 01) MySQLDump semua database menjadi file teks SQL (sebut saja SQLData.sql)

Langkah 02) Lepaskan semua basis data (kecuali skema mysql)

Langkah 03) Matikan mysql

CAVEAT : Untuk benar-benar membersihkan transaksi yang tidak berkomitmen dari File InnoDB, jalankan ini

mysql -uroot -p... -Ae"SET GLOBAL innodb_fast_shutdown = 0;"
service mysql stop

Langkah 04) 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.

Langkah 05) Hapus ibdata1, ib_logfile0 dan ib_logfile1

Pada titik ini, seharusnya hanya ada skema mysql di / var / lib / mysql

Langkah 06) Mulai ulang mysql

Ini akan membuat ulang ibdata1 pada 10MB, ib_logfile0 dan ib_logfile1 masing-masing 1G

Langkah 07) Reload SQLData.sql ke mysql

ibdata1 akan tumbuh tetapi hanya berisi tabel metadata

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 benar-benar 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. !!!

Ada alternatif yang akan mengekstrak tabel InnoDB tanpa menyusut ibdata1.

Langkah 01) 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

Langkah 02) service mysql restart

Langkah 03) Untuk mengekstrak tabel InnoDB tunggal bernama mydb.mytable, lakukan ini:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Ini akan membuat satu file permintaan menyimpan file struktur asli

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

Anda bisa melakukan ini untuk setiap tabel InnoDB. Sayangnya, ibdata1 akan tetap 150GB.

RolandoMySQLDBA
sumber
saat menjalankan ulang dari file .sql saya mendapat kesalahan berikut ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesada ide?
Berlari
@Bisa tolong posting itu sebagai pertanyaan terpisah.
RolandoMySQLDBA
Jika Anda mengatur innodb_file_per_tabledan kemudian melakukan ALTER TABLEpada setiap tabel, dapatkah Anda menghapus file ibdata1 untuk mendapatkan kembali ruang tanpa harus mengembalikan?
SystemParadox
1
@ SystemParadox BENAR-BENAR TIDAK !!!!!!!! Anda akan kehilangan kamus data.
RolandoMySQLDBA
5

Jika Anda ingin mendapatkan kembali ruang ibdata, dump / restore adalah satu-satunya pilihan Anda, seperti yang ditunjukkan Rolando . Mungkin juga yang terbaik bagi kinerja untuk melakukan ini.

Namun, jika Anda hanya ingin memotong kerugian Anda dan 'kehilangan' 150GB itu di harddisk, Anda cukup mengaktifkan innodb_file_per_tabledi my.cnf dan restart server Anda.

Lalu untuk setiap tabel, terbitkan:

ALTER TABLE x DISABLE KEYS;
ALTER TABLE x ENGINE=InnoDB;
ALTER TABLE x ENABLE KEYS; 

Masalahnya di sini adalah bahwa tablespace besar akan memakan waktu cukup lama.

Apa yang saya sarankan adalah mengatur slave dari live db Anda, jalankan konversi pada slave, lalu matikan master / slave dan salin ruang data baru ke master, atau promosikan slave menjadi master setelah ia menangkapnya .

Anda akan mengalami kesulitan melakukan perubahan ini tanpa downtime sama sekali.

Derek Downey
sumber
+1 karena jujur ​​dan mengatakan 'potong kerugianmu.' Anda bisa mengatakan 'gigit peluru' juga.
RolandoMySQLDBA
Anda dapat menggunakan pt-online-schema-change untuk menghindari downtime saat menjalankan tabel alter.
cornernote