Jika saya menggunakan mysqldump --single-transaction, menurut dokumen itu harus melakukan flush tables dengan read lock untuk mendapatkan status yang konsisten dan kemudian memulai transaksi dan tidak ada penulis yang harus menunggu.
Namun, saya telah menangkap situasi berikut tadi malam:
kutipan dari tampilkan daftar proses lengkap:
ratusan dari mereka ...
Command: Query
Time: 291
State: Waiting for table flush
Info: insert into db_external_notification.....
lalu ini:
Command: Query
Time: 1204
State: Sending data
Info: SELECT /*!40001 SQL_NO_CACHE */ * FROM `db_external_notification`
dan sisa utasnya dalam mode Tidur
apakah ada yang tahu apa yang ditunggu-tunggu oleh sisipan ini? Saya tidak melihat tabel FLUSH atau DDL atau apa pun yang disebutkan dalam manual yang dapat menyebabkan kueri menunggu.
perintah mysqldump penuh
mysqldump --quick --add-drop-table --single-transaction --master-data=2 -uxx -pxx dbname
Saya kira --quick berlebihan di sini, mungkin sisa dari waktu sebelumnya, skrip ini sudah sangat tua, tetapi tidak ada salahnya
mysqldump
? Secara khusus, apakah Anda menggunakan--flush-logs
atau--master-data
...? Ada interaksi potensial di antara opsi.Jawaban:
Opsi --single-transaction dari mysqldump tidak berfungsi
FLUSH TABLES WITH READ LOCK;
. Itu menyebabkan mysqldump untuk mengatur transaksi baca berulang untuk semua tabel yang dibuang.Dari pertanyaan Anda, Anda menyatakan bahwa SELECT mysqldump untuk
db_external_notification
tabel menahan ratusan perintah INSERT ke tabel yang sama. Mengapa ini terjadi?Yang paling mungkin adalah kunci pada gen_clust_index (lebih dikenal sebagai Indeks Clustered). Paradigma ini menyebabkan data dan halaman indeks untuk tabel untuk hidup berdampingan. Halaman indeks tersebut didasarkan pada KUNCI UTAMA atau dan indeks RowID yang dibuat secara otomatis (jika tidak ada KUNCI UTAMA).
Anda harus dapat menemukannya dengan menjalankan
SHOW ENGINE INNODB STATUS\G
dan mencari halaman mana pun dari gen_clust_index yang memiliki kunci eksklusif. Melakukan INSERT ke dalam tabel dengan Indeks Clustered memerlukan kunci eksklusif untuk menangani BTREE KUNCI UTAMA, serta serialisasi auto_increment.Saya telah membahas fenomena ini sebelumnya
Aug 08, 2011
: Apakah InnoDB Deadlock eksklusif untuk INSERT / UPDATE / DELETE?Dec 22, 2011
: MySQL deadlock - tidak bisa memulai kembali secara normal?Dec 13, 2012
: MySQL InnoDB mengunci kunci primer pada penghapusan bahkan dalam READ COMMITTEDUPDATE 2014-07-21 15:03 EDT
Silakan lihat baris 614-617 dari PastBin Anda
Perhatikan bahwa baris 617 mengatakan
Apa artinya ini bagiku? Anda memiliki KUNCI UTAMA dengan auto_increment aktif
id
.Maks Anda
id
untuk tabeldb_external_notification
kurang dari1252538391
saat mysqldump diluncurkan. Ketika Anda mengurangi1252538391
dari1252538405
, ini berarti bahwa 14 atau lebih perintah INSERT telah dicoba. Secara internal, ini perlu memindahkan auto_increment dari tabel ini setidaknya 14 kali. Namun, tidak ada yang dapat dilakukan atau bahkan didorong ke dalam Buffer Log karena mengelolaid
celah ini .Sekarang, lihat daftar proses dari PasteBin Anda. Kecuali saya salah hitung, saya melihat 38 Koneksi DB melakukan INSERT (19 Sebelum proses mysqldump (id proses
6155315
), 19 Setelah). Saya yakin 14 atau lebih dari koneksi tersebut dibekukan karena mengelola celah auto_increment.sumber
The
--single-transaction
pilihan untukmysqldump
tidak melakukanFLUSH TABLES WITH READ LOCK
sebelum memulai pekerjaan cadangan tetapi hanya dalam kondisi tertentu. Salah satu syarat tersebut adalah ketika Anda juga menentukan--master-data
opsi.Dalam kode sumber, dari
mysql-5.6.19/client/mysqldump.c
pada baris 5797:Untuk mendapatkan kunci solid pada koordinat binlog yang tepat sebelum memulai transaksi repeatable-read,
--master-data
opsi memicu kunci ini untuk diperoleh dan kemudian dirilis setelah koordinat binlog telah diperoleh.Bahkan,
mysqldump
tidakFLUSH TABLES
diikuti olehFLUSH TABLES WITH READ LOCK
karena melakukan kedua hal itu memungkinkan kunci baca diperoleh lebih cepat dalam kasus di mana flush awal membutuhkan waktu....namun...
Segera setelah telah memperoleh koordinat binlog,
mysqldump
mengeluarkanUNLOCK TABLES
pernyataan, jadi seharusnya tidak ada apa pun yang memblokir sebagai akibat dari flush yang Anda mulai. Seharusnya tidak ada utasWaiting for table flush
sebagai akibat dari transaksi yangmysqldump
ditahan.Ketika Anda melihat sebuah thread di
Waiting for table flush
negara, yang harus berarti bahwaFLUSH TABLES [WITH READ LOCK]
pernyataan itu dikeluarkan dan masih berjalan ketika query mulai - sehingga query harus menunggu flush meja, sebelum dapat mengeksekusi. Dalam kasus daftar proses yang Anda posting,mysqldump
membaca dari tabel yang sama ini, dan kueri telah berjalan untuk sementara waktu, namun kueri pemblokiran belum memblokir selama itu.Ini semua menunjukkan bahwa sesuatu yang lain telah terjadi.
Ada masalah lama yang dijelaskan dalam Bug # 44884 dengan cara
FLUSH TABLES
kerjanya, secara internal.Saya tidak akan terkejut jika masalah ini masih berlanjut,saya akan terkejut jika masalah ini pernah "diperbaiki" karena ini adalah masalah yang sangat kompleks untuk diselesaikan - hampir tidak mungkin untuk benar-benar diperbaiki dalam lingkungan konkurensi tinggi - dan segala upaya untuk memperbaikinya membawa risiko signifikan melanggar sesuatu, atau menciptakan perilaku baru, berbeda, dan masih tidak diinginkan.Sepertinya ini akan menjadi penjelasan untuk apa yang Anda lihat.
Secara khusus:
jika Anda memiliki kueri yang berjalan lama berjalan melawan tabel, dan masalah
FLUSH TABLES
, makaFLUSH TABLES
akan memblokir sampai kueri yang berjalan lama selesai.Selain itu, setiap pertanyaan yang dimulai setelah
FLUSH TABLES
dikeluarkan akan diblokir sampaiFLUSH TABLES
selesai.selain itu, jika Anda membunuh
FLUSH TABLES
kueri, kueri yang memblokir masih akan memblokir kueri yang sudah berjalan lama, kueri yang memblokirFLUSH TABLES
kueri, karena meskipunFLUSH TABLES
kueri yang terbunuh tidak selesai, tabel itu (satu, atau lebih lanjut, terlibat dengan permintaan yang sudah berjalan lama) masih dalam proses disiram, dan bahwa pending flush yang tertunda akan terjadi segera setelah permintaan yang sudah berjalan selesai - tetapi tidak sebelumnya.Kesimpulan yang mungkin di sini adalah bahwa proses lain - mungkin mysqldump lain, atau permintaan yang keliru, atau proses pemantauan yang ditulis dengan buruk mencoba menyiram sebuah tabel.
Permintaan itu kemudian dibunuh atau habis waktu oleh mekanisme yang tidak diketahui, tetapi efek setelahnya bertahan sampai
mysqldump
selesai membaca dari tabel yang bersangkutan.Anda dapat meniru kondisi ini dengan mencoba
FLUSH TABLES
sementara permintaan yang sudah berjalan dalam proses. Kemudian mulai permintaan lain, yang akan diblokir. Kemudian bunuhFLUSH TABLES
kueri, yang tidak akan membuka blokir kueri terbaru. Kemudian bunuh kueri pertama, atau biarkan selesai, dan kueri akhir akan berhasil dijalankan.Sebagai renungan, ini tidak berhubungan:
Itu normal, karena
mysqldump --single-transaction
masalah aSTART TRANSACTION WITH CONSISTENT SNAPSHOT
, yang mencegahnya membuang data yang diubah saat dump sedang berlangsung. Tanpa itu, koordinat binlog yang diperoleh di awal akan menjadi tidak berarti, karena--single-transaction
tidak akan seperti yang diklaimnya. Seharusnya tidak terkait denganWaiting for table flush
masalah ini, karena transaksi ini jelas tidak memiliki kunci.sumber
Saya mengirimkan permintaan fitur: https://support.oracle.com/epmos/faces/BugDisplay?id=27103902 .
Saya juga menulis tambalan terhadap 5.6.37 yang menggunakan metode yang sama dengan --single-transaction - master-data kombinasi dengan --single-transaction --slave-data, yang disediakan apa adanya tanpa jaminan. Gunakan dengan risiko Anda sendiri.
Saya mengujinya dengan proses berikut dengan budak ke master yang sangat sibuk menggunakan banyak tabel InnoDB dengan hubungan FK:
Proses pengiriman tambalan Oracle agak intensif sehingga saya memilih rute ini. Saya dapat mencoba dengan Percona dan / atau MariaDB untuk mengintegrasikannya.
sumber