Mengapa tabel MySQL lumpuh? Bagaimana saya mencegahnya?

9

Saya Administrator situs Moodle yang memiliki tabel Pengguna rusak dan menjadi tidak dapat digunakan.

Untungnya, yang sederhana REPAIR TABLE mdl_usermembuatnya bekerja kembali. Masalahnya adalah saya tidak tahu mengapa itu benar-benar jatuh dan membuatnya tidak dapat digunakan, dan saya ingin memastikan bahwa saya lebih siap di lain waktu.

Saya bukan DBA yang benar-benar berpengalaman - Saya hanya seorang pengembang yang melakukan banyak hal, jadi mohon bersabar.

Saya hanya bisa mengembalikan cadangan, tapi saya kira ada cara untuk mencegah crash.

Tabel-tabel itu adalah utf8_general_ci dan menggunakan MyISAM.

Mengapa tabel MySQL lumpuh? Apa yang bisa saya lakukan untuk mencegah hal itu terjadi?

AeroCross
sumber

Jawaban:

11

Tabel MyISAM agak mudah rusak.

Di header setiap tabel MyISAM adalah penghitung yang melacak berapa banyak file yang terbuka menangani ada di meja.

Jika Anda memulai mysql dan nomor di header tidak cocok dengan jumlah penanganan file yang sebenarnya, mysqld memperlakukan tabel sebagai macet.

Jika sederhana REPAIR TABLE mdl_usermembuatnya berfungsi lagi setiap kali tanpa kehilangan data, ini dapat menunjukkan bahwa Anda memiliki situs yang sangat diperdagangkan untuk menulis mdl_user.

Jika puluhan tabel memerlukan ini REPAIR TABLE, saya akan mengonversi semua tabel ke InnoDB. Namun, jika mdl_usertabel adalah satu-satunya tabel dengan masalah ini, ada sesuatu yang dapat Anda lakukan (untuk contoh ini, katakanlah database adalah moodle);

Jika Anda ingin semua tabel dibiarkan sebagai MyISAM

LANGKAH 01: Buat Skrip Tabel Perbaikan

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

LANGKAH 02: Nyatakan Skrip Perbaikan sebagai file startup

Tambahkan ini ke /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

LANGKAH 03: Mulai ulang mysql

Setiap restart mysql akan memicu Script Tabel Perbaikan

Jika Anda ingin semua tabel menjadi InnoDB

Jalankan kode ini untuk membuat skrip konversi massal tabel MyISAM ke InnoDB, dan melihatnya

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

Setelah Anda puas dengan konten skrip konversi, kemudian jalankan

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

UPDATE 2012-03-15 14:00 EDT

@ Kevin , Saat menggunakan MyISAM, bagaimana jika kehabisan Disk Space adalah masalah Anda?

Berikut adalah sesuatu yang perlu dipertimbangkan: Menurut Panduan Studi Sertifikasi MySQL 5.0 ,

masukkan deskripsi gambar di sini

bulletpoint # 11 mengatakan yang berikut di Halaman 408.409 Bagian 29.2:

Jika Anda kehabisan ruang disk saat menambahkan baris ke tabel MyISAM, tidak ada kesalahan terjadi. Server menunda operasi sampai ruang tersedia, dan kemudian menyelesaikan operasi.

Ketika Anda kehabisan ruang disk, jangan hanya mematikan atau membunuh mysql. Hitungan pegangan file terbuka di MyISAM yang saat ini digunakan tidak akan dihapus. Dengan demikian, tabel MyISAM ditandai macet. Jika Anda dapat mengosongkan ruang disk dalam volume data dengan mysqld masih berjalan, mysqld akan menjadi prajurit pada saat ruang disk tersedia.

RolandoMySQLDBA
sumber
Respon luar biasa. Tidak tahu sedikit tentang pegangan file, dan Anda telah memecahkan bagaimana saya bisa mencegah (atau secara otomatis memperbaiki) jika ada masalah. Adakah saran untuk keamanan jika situs tersebut memang banyak menulis ke mdl_user (atau tabel lainnya)?
AeroCross
Anda harus melakukan tiga hal: 1) meningkatkan RAM, 2) meningkatkan max_connections, 3) beralih ke InnoDB.
RolandoMySQLDBA
Noob di sini. Di mana saya "menjalankan" kode ini? Dari file yang diunggah ke server atau dari beberapa baris perintah?
UncaughtTypeError
0

Saya juga mengelola situs moodle di mysql, dan penyebab paling umum kerusakan tabel bagi kami adalah kehabisan ruang disk.

Kevin
sumber
@RolandoMySQLDBA - yeah, ruang disk tentunya merupakan masalah (terkait dengan beberapa proses lain, dan filosofi manajemen secara umum). Sayangnya, kami tidak melihat masalah teratasi dengan sendirinya saat ruang kosong, atau tidak menyelesaikannya dengan cepat. Tanggapan saya hanya untuk menunjukkan bahwa dengan contoh moodle / mysql kami, masalah ruang disk dapat menyebabkan crash tabel, terlepas dari apa yang seharusnya dilakukan mysql / myisam.
Kevin
-3

Saya menemukan satu baris yang bagus untuk mengonversi semua tabel ke InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName
Dmitry
sumber
Kode mungkin ok untuk itu tetapi tidak menjawab pertanyaan bagian pertama (Mengapa tabel MySQL crash?). Jika Anda bermaksud menjawab bagian kedua (Bagaimana mencegahnya?), Tolong tambahkan beberapa penjelasan.
ypercubeᵀᴹ
Tambahkan juga detail lebih lanjut. Apakah menjalankan ini mengonversi semua tabel dalam database? Atau seluruh server? Apa yang akan terjadi jika tabel gagal dikonversi dan kami mendapatkan kesalahan? Mungkinkah kita berakhir dengan beberapa tabel dikonversi dan beberapa tersisa di MyiSAM? Secara umum, hal-hal lain apa yang harus dipertimbangkan DBA sebelum menjalankan ini?
ypercubeᵀᴹ