N सेकंड के बाद धीमी MySQL क्वेरी को स्वचालित रूप से कैसे मारें?


16

मैं ऐसा करने के लिए एक अच्छी तरह से परीक्षण किए गए बैश स्क्रिप्ट (या वैकल्पिक समाधान) की तलाश कर रहा हूं, ताकि अधिक से अधिक थकावट से बचा जा सके। मुझे पता है कि यह लक्षणों से लड़ रहा है, लेकिन वास्तव में इस तरह की स्क्रिप्ट की आवश्यकता अल्पकालिक समाधान के रूप में है।


MySQL के कौन से संस्करण चला रहे हैं ???
RolandoMySQLDBA

mysql संस्करण ५.५ है
अल्फांस

जवाबों:


21

बाहर की जाँच pt-मार से आदेश percona टूलकिट

और .. अपने सिस्टम की निगरानी शुरू कर दें - myinql के लिए बेहतर कैक्टि टेम्पलेट के साथ मुनिन , कैक्टि । mysql की धीमी क्वेरी को लॉग करना एक अच्छा विचार होगा।


सुझावों के बारे में धन्यवाद, लेकिन वास्तव में "एकबारगी" स्क्रिप्ट की तलाश करें।
अलाफेन

5
पीटी-मार बहुत अच्छी तरह से परीक्षण किया गया है और आपकी सटीक समस्या को हल करता है। कमांड लाइन के मापदंडों का पता लगाने और इसे चालू करने में 10 मिनट लगते हैं। आपको और क्या चाहिए?
आरोन ब्राउन

12

यदि आपके पास MySQL 5.1 है, जहां INFORMATION_SCHEMA में प्रक्रिया सूची है, तो आप 20 मिनट (1200 सेकंड) से अधिक समय तक चलने वाले क्वेरी के लिए mysql क्लाइंट के भीतर से बल्क में KILL QUERY कमांड उत्पन्न करने के लिए ऐसा कर सकते हैं:

SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G

आप एक विशिष्ट क्वेरी, लंबे समय से चल रहे प्रश्नों के विरुद्ध TIME फ़ील्ड या किसी विशिष्ट डेटाबेस के विरुद्ध DB फ़ील्ड देखने के लिए INFO फ़ील्ड के विरुद्ध क्लॉस कर सकते हैं।

यदि आप रूट @ लोकलहोस्ट हैं, तो आपके पास इसे चलाने के लिए पूरे विशेषाधिकार होने चाहिए

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

आप इसे निम्न प्रकार से लिख सकते हैं:

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

यहाँ एक और भिन्नता है:

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 आपके पास एक myDB निर्दिष्ट नहीं है क्योंकि मैंने स्पष्ट रूप से information_schema.processlist से पूरी तरह से योग्य टैब्लेमनाम के रूप में पढ़ा है।

यहाँ एक प्रदर्शन है जो आपको देखना चाहिए। इस उदाहरण के लिए, मैं उन सभी प्रक्रियाओं के KILL कमांड की गूंज करूंगा जिनका समय> 20000 सेकंड:

[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@***** ~]#

मैं पिछले 5 सालों से इस तकनीक को कर रहा हूं। वास्तव में, मैंने यह उत्तर पिछले साल डीबीए स्टैकएक्सचेंज को प्रस्तुत किया था और इसे स्वीकार कर लिया गया था


रॉलेंड, क्या आप कृपया इन्हें स्पष्ट कर सकते हैं: क्या यह कमांड लगातार है, या बार-बार चलाने की आवश्यकता है? कमांड में यह निर्दिष्ट किया जाना चाहिए कि mysql उपयोगकर्ता 'root' है और डेटाबेस का नाम myDB है? धन्यवाद
alfish

मैंने अपना उत्तर अपडेट कर दिया।
RolandoMySQLDBA

धन्यवाद, लेकिन अपने आखिरी रेसिपी को बैश स्क्रिप्ट में बदलने के बाद, मुझे मिलता है: पंक्ति 1 पर ERROR 1064 (42000): आपके SQL सिंटैक्स में कोई त्रुटि है; लाइन 1 पर '' के पास उपयोग करने के लिए सही सिंटैक्स के लिए आपके MySQL सर्वर संस्करण से मेल
खाने

किस SQL ​​कमांड ने वह त्रुटि उत्पन्न की ???
रोलैंडमाइसीडीडीबीए

रोलैंड SF एक सैंडबॉक्स नहीं है। समाधान के रूप में कुछ सुझाने से पहले बेहतर परीक्षण करें। इसके अलावा, जब सभी कनेक्शन संतृप्त होते हैं, तो mysql आपकी प्रक्रिया को कैसे चलाने वाला है, यह मानते हुए कि यह दोषपूर्ण नहीं है?
अल्फांस

6

मुझे निम्नलिखित कोड-स्निप यहां मिली :

अद्यतन 2013-01-14: एक अनाम संकेत था कि यह संभावित खतरनाक है और साथ ही प्रतिकृति प्रक्रियाओं को भी मार सकता है। इसलिए अपने जोखिम पर उपयोग करें:

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

ऊपर के स्निपेट में स्थिर समय क्या है?
अल्फांस

@alfish मैं लेखक नहीं हूं - लेकिन मैं कहूंगा कि यह एक नियमित अभिव्यक्ति है जो सभी समय के मूल्यों से मेल खाती है जिसमें कम से कम दो अंक होते हैं। तो यहां धारणा यह है कि 10 बहुत लंबा है।
नेल्स

1

MySQL 5.7 इसके बाद आप सभी "सेलेक्ट" रीड क्वेरी के लिए इसे स्वचालित रूप से प्राप्त करने के लिए max_execution_time चर का उपयोग कर सकते हैं।


0

यदि आप अपटाइम पसंद करते हैं तो मैं बैश समाधान की कोशिश नहीं करूंगा!

यदि आपके पास कोड तक पहुंच है, तो आप वास्तव में यहां बताए गए तरीके का उपयोग करके सेलेक्ट स्टेटमेंट पर अधिकतम निष्पादन समय निर्धारित कर सकते हैं :

SELECT 
MAX_EXECUTION_TIME = 1000 --in milliseconds
* 
FROM table;

अन्यथा, सर्वर पर:

/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query

Pt-किल को स्थापित करें:

$ wget percona.com/get/pt-kill

अपनी प्रक्रिया सूची का स्नैपशॉट लें:

$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt

स्नैपशॉट पर टेस्ट pt-किल:

$ ./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

सुनिश्चित करें कि मैच के नियम आपके मामले के अनुकूल हैं। ये सभी 45 सेकंड में सभी एक्सट्यूट स्टेटमेंट्स को मार देंगे। एक बार जब आप सुनिश्चित हो जाते हैं, तो 10 सेकंड के अंतराल पर कथन को निष्पादित करने के लिए इस कमांड को संशोधित करें और चलाएं:

$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.