วิธีการฆ่า MySQL ที่ช้าโดยอัตโนมัติหลังจาก N วินาที?


16

ฉันกำลังมองหาสคริปต์ทุบตีทดสอบ (หรือโซลูชันทางเลือก) ให้ทำเช่นนั้นเพื่อหลีกเลี่ยง max_connection ที่จะหมด ฉันรู้ว่ามันกำลังต่อสู้กับอาการ แต่ต้องการสคริปต์เช่นนั้นเป็นทางออกระยะสั้น


MySQL เวอร์ชันใดที่คุณใช้อยู่ ???
RolandoMySQLDBA

รุ่น mysql คือ 5.5
alfish

คำตอบ:


21

ตรวจสอบPT-ฆ่าคำสั่งจากเครื่องมือ Percona

และ .. จะเริ่มการตรวจสอบระบบของคุณ - munin , cactiด้วยcacti template ที่ดีกว่าสำหรับ mysqlทุกอย่างเพื่อให้คุณเข้าใจว่าเกิดอะไรขึ้น เข้าสู่ระบบแบบสอบถาม MySQL ช้าจะเป็นความคิดที่ดีเช่นกัน


ขอบคุณเกี่ยวกับคำแนะนำ แต่มองหาสคริปต์ "one-off"
alfish

5
pt-kill ได้รับการทดสอบเป็นอย่างดีและแก้ไขปัญหาที่แน่นอนของคุณ ใช้เวลาประมาณ 10 นาทีในการหาพารามิเตอร์บรรทัดคำสั่งและเริ่มทำงาน คุณต้องการอะไรอีก
Aaron Brown

12

หากคุณมี 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 ปีที่ผ่านมาและมันก็เป็นที่ยอมรับ


Roland, คุณช่วยอธิบายให้ชัดเจนได้ไหมว่า: คำสั่งนี้ขัดขืนหรือจำเป็นต้องรันบ่อยครั้งหรือไม่? สิ่งที่ควรทดแทนในคำสั่งสมมติว่าผู้ใช้ mysql คือ 'root' และชื่อฐานข้อมูลคือ myDB? ขอบคุณ
alfish

ฉันปรับปรุงคำตอบของฉัน
RolandoMySQLDBA

ขอบคุณ แต่หลังจากเปลี่ยนสูตรสุดท้ายของคุณให้เป็นสคริปต์ทุบตีฉันได้รับ: ข้อผิดพลาด 1064 (42000) ที่บรรทัดที่ 1: คุณมีข้อผิดพลาดในไวยากรณ์ SQL ของคุณ; ตรวจสอบคู่มือที่สอดคล้องกับรุ่นเซิร์ฟเวอร์ MySQL ของคุณเพื่อหาไวยากรณ์ที่ถูกต้องที่จะใช้ใกล้ '' ที่บรรทัดที่ 1
alfish

คำสั่ง SQL ใดที่สร้างข้อผิดพลาดนั้น ???
RolandoMySQLDBA

Roland SF ไม่ใช่ sandbox ทดสอบให้ดีกว่าก่อนที่คุณจะแนะนำวิธีแก้ปัญหา นอกจากนี้เมื่อการเชื่อมต่อทั้งหมดอิ่มตัววิธี mysql จะเรียกใช้ขั้นตอนของคุณโดยสมมติว่ามันไม่ผิดพลาด?
alfish

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

@alfish ฉันไม่ใช่ผู้แต่ง - แต่ฉันจะบอกว่านี่เป็นนิพจน์ทั่วไปที่ตรงกับค่าเวลาทั้งหมดที่มีตัวเลขอย่างน้อยสองหลัก สมมติฐานที่นี่คือ 10 ยาวเกินไป
นิลส์

1

MySQL 5.7 เป็นต้นไปคุณสามารถใช้ตัวแปร max_execution_time เพื่อทำสิ่งนี้โดยอัตโนมัติสำหรับคำสั่งการอ่าน "SELECT" ทั้งหมด


0

ฉันจะไม่ลองใช้วิธีทุบตีถ้าคุณชอบเวลาว่าง

หากคุณสามารถเข้าถึงรหัสคุณสามารถกำหนดเวลาดำเนินการสูงสุดในคำสั่ง 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.