Bagaimana saya bisa mengonfigurasi MySQL Innodb untuk menangani ribuan sisipan per jam?

10

Saya memiliki situs web lalu lintas yang sangat tinggi di mana ada kemungkinan ribuan catatan baru dimasukkan setiap jam.

Kesalahan yang satu ini melumpuhkan situs:

PDOException: SQLSTATE[40001]: Serialization failure: 1213 
Deadlock found when trying to get lock; 
try restarting transaction: INSERT INTO {location_instance} 
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0, 
:db_insert_placeholder_1, :db_insert_placeholder_2, 
:db_insert_placeholder_3, :db_insert_placeholder_4); 
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] => 
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] => 
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )

Saya akan sangat terkejut jika MySQL tidak dapat menangani beban jenis ini. Jadi, pertanyaan saya kemudian, apakah ini masalah database dan bagaimana saya bisa mengkonfigurasi MySQL untuk dapat menangani lalu lintas sebanyak ini?

Saya memiliki salinan situs web saya disiapkan di server pengembangan dengan skrip yang mensimulasikan beban konten yang ditambahkan ke situs web. Saya menjalankan Ubuntu, LAMP stack, dengan 16GB RAM.

Memang, saya tidak begitu paham tentang basis data. Bahkan, saya mulai dengan my.cnf default yang datang dengannya setelah 'apt-get install' selesai. Tabel adalah semua Innodb. Apa yang memulai pengaturan dan pendekatan konfigurasi yang Anda rekomendasikan untuk mulai menyelesaikan masalah ini?

Beri tahu saya informasi apa lagi yang mungkin Anda butuhkan.

Terima kasih

pengguna658182
sumber
Anda mulai dengan my.cnf default untuk produksi? Man, kamu harus lebih mengoptimalkannya. Akan lebih detail dalam jawaban saya. :-)

Jawaban:

11

Anda berhadapan dengan jalan buntu, bukan masalah bottleneck kinerja.

Jika Anda memiliki seribu catatan baru per jam, Anda jauh sekali jauh dari jangkauan batas MySQL. MySQL dapat menangani setidaknya 50 kali beban Anda.

Kebuntuan disebabkan oleh kode aplikasi dan bukan kesalahan server database. Deadlock tidak dapat diperbaiki di sisi server MySQL, kecuali dalam beberapa situasi tertentu.

InnoDBdapat menampilkan informasi kebuntuan terperinci dengan menjalankan SHOW ENGINE INNODB STATUSdi prompt MySQL, atau dengan mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS".

Namun, ini hanya menunjukkan kebuntuan terakhir yang terjadi, tidak ada kebuntuan log.

Untungnya, ada alat pt-deadlock-logger yang menangani masalah itu, mengurus InnoDBstatus polling dan menyimpan semua informasi kebuntuan sebelum disegarkan dengan kebuntuan baru.

Keberanian
sumber
Senang mendengarnya! Saya melihat perintah status menunjukkan informasi tentang kunci dan kueri serta tabel terkait. Mengingat ini ada dalam kode saya, bagaimana saya bisa menggunakan informasi ini dari perintah status untuk mulai men-debug masalah? Permintaan PHP PDO cukup mudah - sambungkan, siapkan, jalankan, ulangi. Saya akan senang memposting kode apa pun atau pesan status jika itu akan membantu.
user658182
@ user658182 periksa pos ini di stackoverflow tentang cara menangani deadlock: bagaimana cara menghindari kebuntuan mysql ditemukan ketika mencoba untuk mendapatkan kunci
Valor
1
@max-vernon terima kasih untuk edit sintaks, jelas bahasa Inggris itu bukan bahasa ibu saya :-).
Valor
1
-e "TUNJUKKAN STATUS ENGINE INNODB"
mesin terbang
8

Ini bisa sesederhana salah satu bagian dari kode Anda menjalankan transaksi:

insert into t1...
insert into t2...
commit;

sementara bagian lain dari kode Anda memodifikasi tabel yang sama dalam urutan berbeda:

delete from t2 where...
delete from t1 where...
commit;

Jika kedua transaksi tersebut berjalan pada saat yang sama, kondisi lomba dapat terjadi: transaksi pertama tidak dapat dimodifikasi t2karena dikunci oleh transaksi kedua; sedangkan transaksi kedua juga diblokir karena t1dikunci oleh transaksi pertama. MySQL memilih satu transaksi untuk menjadi "korban" di mana INSERT / UPDATE / DELETE gagal. Aplikasi perlu menangkap kesalahan itu, dan coba lagi pernyataan - mungkin setelah jeda sehingga transaksi lain memiliki waktu untuk menyelesaikannya. Tidak ada hubungannya dengan batas kapasitas, hanya waktu yang tidak menguntungkan yang dapat diperburuk dengan cara kode diatur. Beralih di sekitar HAPUS dalam transaksi # 2, atau INSERT dalam transaksi # 1, dan kemudian tidak ada konflik - setiap transaksi akan menunggu akses ke tabel yang dibutuhkan.

Di MySQL 5.6, Anda dapat menjalankan dengan opsi innodb_print_all_deadlocks diaktifkan untuk mengumpulkan info tentang semua deadlock (bukan hanya yang terbaru) di log kesalahan MySQL.

[Penafian Wajib: Saya adalah karyawan Oracle. Di atas adalah pandangan pribadi saya bukan pernyataan resmi.]

Max Webster
sumber