ฉันกำลังมองหาสคริปต์ทุบตีทดสอบ (หรือโซลูชันทางเลือก) ให้ทำเช่นนั้นเพื่อหลีกเลี่ยง max_connection ที่จะหมด ฉันรู้ว่ามันกำลังต่อสู้กับอาการ แต่ต้องการสคริปต์เช่นนั้นเป็นทางออกระยะสั้น
ฉันกำลังมองหาสคริปต์ทุบตีทดสอบ (หรือโซลูชันทางเลือก) ให้ทำเช่นนั้นเพื่อหลีกเลี่ยง max_connection ที่จะหมด ฉันรู้ว่ามันกำลังต่อสู้กับอาการ แต่ต้องการสคริปต์เช่นนั้นเป็นทางออกระยะสั้น
คำตอบ:
ตรวจสอบPT-ฆ่าคำสั่งจากเครื่องมือ Percona
และ .. จะเริ่มการตรวจสอบระบบของคุณ - munin , cactiด้วยcacti template ที่ดีกว่าสำหรับ mysqlทุกอย่างเพื่อให้คุณเข้าใจว่าเกิดอะไรขึ้น เข้าสู่ระบบแบบสอบถาม MySQL ช้าจะเป็นความคิดที่ดีเช่นกัน
หากคุณมี MySQL 5.1 ซึ่งรายการกระบวนการอยู่ใน INFORMATION_SCHEMA คุณสามารถทำสิ่งนี้เพื่อสร้างคำสั่ง KILL QUERY จำนวนมากจากภายในไคลเอนต์ mysql สำหรับการสืบค้นที่ใช้เวลานานกว่า 20 นาที (1200 วินาที):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
คุณสามารถทำ WHERE clause กับฟิลด์ INFO เพื่อค้นหาเคียวรีเฉพาะฟิลด์ TIME กับเคียวรีที่รันนานหรือฟิลด์ DB กับฐานข้อมูลเฉพาะ
หากคุณเป็น root @ localhost คุณควรมีสิทธิ์เต็มที่ในการรันดังนี้
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
คุณสามารถ crontab นี้ดังนี้:
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 ของกระบวนการทั้งหมดที่มีเวลา> 20,000 วินาที:
[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 ปีที่ผ่านมา ในความเป็นจริงฉันส่งคำตอบนี้ไป DBA StackExchange ปีที่ผ่านมาและมันก็เป็นที่ยอมรับ
ฉันพบรหัสต่อไปนี้ที่นี่ :
อัปเดต 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
MySQL 5.7 เป็นต้นไปคุณสามารถใช้ตัวแปร max_execution_time เพื่อทำสิ่งนี้โดยอัตโนมัติสำหรับคำสั่งการอ่าน "SELECT" ทั้งหมด
ฉันจะไม่ลองใช้วิธีทุบตีถ้าคุณชอบเวลาว่าง
หากคุณสามารถเข้าถึงรหัสคุณสามารถกำหนดเวลาดำเนินการสูงสุดในคำสั่ง SELECT โดยใช้วิธีการที่ระบุไว้ที่นี่ :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
มิฉะนั้นบนเซิร์ฟเวอร์:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
ติดตั้ง pt-kill:
$ wget percona.com/get/pt-kill
ถ่ายภาพรายการกระบวนการของคุณ:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
ทดสอบ pt-kill บนภาพรวม:
$ ./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
ตรวจสอบให้แน่ใจว่ากฎการแข่งขันเหมาะกับกรณีของคุณ ด้านบนเหล่านี้จะฆ่าคำสั่ง Execute ทั้งหมดใน 45 วินาที เมื่อคุณแน่ใจแล้วปรับเปลี่ยนและเรียกใช้คำสั่งนี้เพื่อดำเนินการคำสั่งที่ช่วงเวลา 10 วินาที:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill