Saya mencari skrip bash yang teruji dengan baik (atau solusi alternatif) untuk melakukannya, untuk menghindari max_connection menjadi habis. Saya tahu itu melawan gejala, tetapi benar-benar membutuhkan skrip seperti solusi jangka pendek.
Saya mencari skrip bash yang teruji dengan baik (atau solusi alternatif) untuk melakukannya, untuk menghindari max_connection menjadi habis. Saya tahu itu melawan gejala, tetapi benar-benar membutuhkan skrip seperti solusi jangka pendek.
Jawaban:
lihat perintah pt-kill dari perkona toolkit .
dan .. mulailah memonitor sistem Anda - munin , kaktus dengan templat kaktus yang lebih baik untuk mysql , apa pun sehingga Anda mendapatkan ide tentang apa yang terjadi. mencatat permintaan lambat mysql akan menjadi ide yang bagus juga.
Jika Anda memiliki MySQL 5.1 di mana daftar proses ada di INFORMATION_SCHEMA, Anda dapat melakukan ini untuk menghasilkan perintah KILL QUERY dalam jumlah besar dari dalam klien mysql untuk kueri yang berjalan lebih dari 20 menit (1200 detik):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
Anda bisa melakukan klausa WHERE terhadap bidang INFO untuk mencari kueri tertentu, bidang TIME terhadap kueri yang sudah berjalan lama, atau bidang DB terhadap database tertentu.
Jika Anda root @ localhost, Anda harus memiliki hak penuh untuk menjalankan ini sebagai berikut
SECONDS_TOO_LONG=1200
KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
Anda dapat crontab ini sebagai berikut:
SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
fi
Berikut variasi lainnya:
SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
KILLPROC_SQLSTMT="SELECT CONCAT('KILL QUERY ',id,';') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" > /tmp/kill_log_queries.sql
mysql -uroot -ppassword < /tmp/kill_log_queries.sql
fi
BTW Anda tidak harus menentukan myDB karena saya secara eksplisit membaca dari information_schema.processlist sebagai nama tab yang sepenuhnya memenuhi syarat.
Ini adalah demonstrasi dari apa yang harus Anda lihat. Untuk contoh ini, saya akan mengulangi perintah KILL dari semua proses yang waktunya> 20000 detik:
[root@***** ~]# mysql `lwdba_connect` -ANe"SELECT GROUP_CONCAT('KILL ',id,'; ' SEPARATOR ' ') FROM information_schema.processlist WHERE time > 25000 AND user<>'system user';"
+----------------------------------------------------+
| KILL 180186; KILL 180141; KILL 176419; KILL 3; |
+----------------------------------------------------+
[root@***** ~]#
Saya telah melakukan teknik ini selama 5 tahun terakhir. Bahkan, saya mengirimkan jawaban ini ke DBA StackExchange tahun lalu dan diterima .
Saya menemukan potongan kode berikut di sini :
Pembaruan 2013-01-14: Ada petunjuk anonim bahwa ini berpotensi berbahaya dan dapat membunuh proses replikasi juga. Jadi gunakan dengan risiko Anda sendiri:
mysql -e 'show processlist\G' |\
egrep -b5 'Time: [0-9]{2,}' |\
grep 'Id:' |\
cut -d':' -f2 |\
sed 's/^ //' |\
while read id
do
mysql -e "kill $id;"
done
MySQL 5.7 dan seterusnya Anda dapat menggunakan variabel max_execution_time untuk menyelesaikan ini secara otomatis untuk semua permintaan baca "SELECT".
Saya tidak akan mencoba solusi bash jika Anda suka waktu aktif!
Jika Anda memiliki akses ke kode Anda sebenarnya dapat mengatur waktu eksekusi maksimum pada pernyataan SELECT menggunakan metode yang diuraikan di sini :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
Jika tidak, di server:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
Pasang pt-kill:
$ wget percona.com/get/pt-kill
Ambil snapshot dari daftar proses Anda:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
Uji pt-kill pada snapshot:
$ ./pt-kill --test-matching processlist.txt --busy-time 45 --kill-busy-commands 'Execute' --victims all --print
# 2019-02-25T17:34:37 KILL 45710302 (Execute 374 sec) SELECT\n\tCOUNT(DISTINCT(LP.sessionId))\nFROM lp_traffic LP\nINNER JOIN orders O ON O.orderId = LP.order
# 2019-02-25T17:34:37 KILL 45713515 (Execute 67 sec) SELECT \n\tCOUNT(DISTINCT(CASE WHEN T.response = 'SUCCESS' AND T.isVoid = 0 AND (T.txnType IN
Pastikan aturan kecocokan cocok dengan kasus Anda. Ini di atas akan membunuh semua pernyataan Jalankan lebih dari 45 detik. Setelah Anda yakin maka modifikasi dan jalankan perintah ini untuk menjalankan pernyataan pada interval 10 detik:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill