ฉันจะฆ่ากระบวนการทั้งหมดใน Mysql“ show processlist” ได้อย่างไร?


121

เนื่องจากฉันเห็นกระบวนการมากมายที่นั่นและคอลัมน์ "เวลา" จะแสดงค่ามหาศาลสำหรับกระบวนการทั้งหมด


คุณสามารถรีสตาร์ท mysqld ได้เช่นsudo service mysqld restart
philfreo

คำตอบ:


108

คุณต้องฆ่าพวกมันทีละคน MySQL ไม่มีคำสั่ง kill จำนวนมาก คุณสามารถเขียนสคริปต์เป็นภาษาใดก็ได้ตัวอย่างเช่นใน PHP คุณสามารถใช้สิ่งต่างๆเช่น:

$result = mysql_query("SHOW FULL PROCESSLIST");
while ($row=mysql_fetch_array($result)) {
  $process_id=$row["Id"];
  if ($row["Time"] > 200 ) {
    $sql="KILL $process_id";
    mysql_query($sql);
  }
}

เป็นความคิดที่ดี. ลองแปลงมันเป็นเชลล์สคริปต์บน cron ... !
M. Faraz

4
Shellfor i in {994..1145}; do mysql -uroot -p123456 -e "kill $i" ; done
zhuguowei

mysql -u -p -e "แสดงรายการกระบวนการ" | grep Sleep | awk '{print $ 1}' | ขณะอ่าน LINE; ทำ mysql -u -p -e "kill $ LINE"; done
user3770797

213

ปฏิบัติการฆ่าจำนวนมากช่วยประหยัดเวลา ทำใน MySql เอง:

เรียกใช้คำสั่งเหล่านี้

mysql> select concat('KILL ',id,';') from information_schema.processlist
where user='root' and time > 200 into outfile '/tmp/a.txt';

mysql> source /tmp/a.txt;

การอ้างอิง

---------edit------------

หากคุณไม่ต้องการจัดเก็บในไฟล์ให้จัดเก็บในไฟล์ variable

เพียงแค่เรียกใช้ในพรอมต์คำสั่งของคุณ

> out1=$(mysql -B test -uroot -proot --disable-column-names  -e "select concat('KILL ',id,';') from information_schema.processlist where user='root' and time > 200;")

> out2= $(mysql -B test -uroot -proot --disable-column-names  -e "$out1")

13
โปรดอย่าลืมอ้างอิงแหล่งที่มา: mysqlperformanceblog.com/2009/05/21/…
Artem Goutsoul

2
@ArtemGoutsoul แต่ฉันจำไม่ได้ว่าฉันอ้างถึงไซต์นี้ แนวโน้มของฉันเองในการทำเช่นนี้
Angelin Nadar

@JanusTroelsen แต่คำตอบของฉันคือหลังจาก 3 ปี '12
Angelin Nadar

1
@Angelin Nadar ขอบคุณ!
Silver Light

1
@ShankarDamodaran SURE
Angelin Nadar

16

ฉันได้ค้นหาวิธีการแยกวิเคราะห์ผ่าน MySQL ด้วยคำสั่ง SHOW PROCESSLIST และจบลงด้วย one-liner ใน Shell:

mysqladmin processlist -u <USERNAME> -p<PASSWORD> | \
awk '$2 ~ /^[0-9]/ {print "KILL "$2";"}' | \
mysql -u <USERNAME> -p<PASSWORD>
  • รายการกระบวนการ mysqladminจะพิมพ์ตารางที่มีรหัสเธรด
  • awkจะแยกวิเคราะห์จากคอลัมน์ที่สองเฉพาะตัวเลข (รหัสเธรด) และสร้างคำสั่ง MySQL KILL
  • และสุดท้ายการโทรไปยังmysqlครั้งสุดท้ายจะดำเนินการคำสั่งที่ส่ง

คุณสามารถรันgrepก่อนคำสั่งawkเพื่อกรองชื่อฐานข้อมูลเฉพาะ


13

หรือ ... ในเปลือก ...

service mysql restart

ใช่ฉันรู้ว่าฉันขี้เกียจ แต่มันก็มีประโยชน์เช่นกัน


10
นี่เป็นความคิดที่แย่มาก ... พิเศษถ้าคุณมีตารางเอ็นจิ้นที่ตั้งไว้ในหน่วยความจำข้อมูลทั้งหมดจะหายไป ... หรือถ้าคุณใช้ประเภท
เอ็นจิ้น

8
นอกจากนี้ยังฆ่ากระบวนการทั้งหมดในฐานข้อมูลทั้งหมด
Diego AndrésDíaz Espinoza

9

สำหรับ mariaDB เท่านั้น

มันไม่ได้ง่ายไปกว่านี้แล้วเพียงแค่รันสิ่งนี้ใน mysql prompt

kill USER username;

มันจะฆ่ากระบวนการทั้งหมดภายใต้ชื่อผู้ใช้ที่ระบุ เนื่องจากคนส่วนใหญ่ใช้ผู้ใช้เดียวกันเพื่อวัตถุประสงค์ทั้งหมดมันได้ผล!

ฉันได้ทดสอบสิ่งนี้บน MariaDB แล้วไม่แน่ใจเกี่ยวกับ mysql


3
MySQL มีอยู่ในเวอร์ชันใด ฉันไม่เห็นมันบันทึกไว้ในMySQL 5.7 อ้างอิง ; KILL [CONNECTION | QUERY] processlist_idมีหลักฐานว่ามันเป็นไปได้ที่จะฆ่าโดยไม่มีผู้ใช้: ฉันลองใช้แบบสอบถามของคุณใน MySQL 5.6.34 และถือว่าเป็นข้อผิดพลาดทางไวยากรณ์
Birchlabs

4
ฉันได้ลองสิ่งนี้ในพรอมต์ MySQL 5.6.34: mysql> kill user root; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'root' at line 1 คำตอบของคุณอาจเป็นคุณลักษณะเฉพาะสำหรับ MariaDB เท่านั้น
Birchlabs

สิ่งนี้ใช้ไม่ได้กับ Mysql โปรดอ่านก่อนโพสต์คำแนะนำที่เกี่ยวข้องกับระบบ DB อื่น ๆ ...
RyanH

7

ต่อไปนี้จะสร้างขั้นตอนการจัดเก็บอย่างง่ายที่ใช้เคอร์เซอร์เพื่อฆ่ากระบวนการทั้งหมดทีละรายการยกเว้นกระบวนการที่ใช้อยู่ในปัจจุบัน:

DROP PROCEDURE IF EXISTS kill_other_processes;

DELIMITER $$

CREATE PROCEDURE kill_other_processes()
BEGIN
  DECLARE finished INT DEFAULT 0;
  DECLARE proc_id INT;
  DECLARE proc_id_cursor CURSOR FOR SELECT id FROM information_schema.processlist;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;

  OPEN proc_id_cursor;
  proc_id_cursor_loop: LOOP
    FETCH proc_id_cursor INTO proc_id;

    IF finished = 1 THEN 
      LEAVE proc_id_cursor_loop;
    END IF;

    IF proc_id <> CONNECTION_ID() THEN
      KILL proc_id;
    END IF;

  END LOOP proc_id_cursor_loop;
  CLOSE proc_id_cursor;
END$$

DELIMITER ;

สามารถรันด้วยSELECTs เพื่อแสดงกระบวนการก่อนและหลังดังนี้:

SELECT * FROM information_schema.processlist;
CALL kill_other_processes();
SELECT * FROM information_schema.processlist;

6

เมื่อเร็ว ๆ นี้ฉันต้องทำสิ่งนี้และฉันก็คิดสิ่งนี้ขึ้นมา

-- GROUP_CONCAT turns all the rows into 1
-- @q:= stores all the kill commands to a variable
select @q:=GROUP_CONCAT(CONCAT('KILL ',ID) SEPARATOR ';')  
FROM information_schema.processlist 
-- If you don't need it, you can remove the WHERE command altogether
WHERE user = 'user';
-- Creates statement and execute it
PREPARE stmt FROM @q;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

ด้วยวิธีนี้คุณไม่จำเป็นต้องจัดเก็บลงไฟล์และเรียกใช้แบบสอบถามทั้งหมดด้วยคำสั่งเดียว


5

ฆ่าคำถามที่เลือกทั้งหมด

select concat('KILL ',id,';') 
from information_schema.processlist 
where user='root' 
  and INFO like 'SELECT%' into outfile '/tmp/a.txt'; 
source /tmp/a.txt;

5

หากคุณไม่มี information_schema:

mysql -e "show full processlist" | cut -f1 | sed -e 's/^/kill /' | sed -e 's/$/;/' ;  > /tmp/kill.txt
mysql> . /tmp/kill.txt

4

เข้าสู่ระบบ Mysql ในฐานะผู้ดูแลระบบ:

 mysql -uroot -ppassword;

และกว่ารันคำสั่ง:

mysql> show processlist;

คุณจะได้รับสิ่งต่อไปนี้:

+----+-------------+--------------------+----------+---------+------+-------+------------------+
| Id | User        | Host               | db       | Command | Time | State | Info             |
+----+-------------+--------------------+----------+---------+------+-------+------------------+
| 49 | application | 192.168.44.1:51718 | XXXXXXXX | Sleep   |  183 |       | NULL             ||
| 55 | application | 192.168.44.1:51769 | XXXXXXXX | Sleep   |  148 |       | NULL             |
| 56 | application | 192.168.44.1:51770 | XXXXXXXX | Sleep   |  148 |       | NULL             |
| 57 | application | 192.168.44.1:51771 | XXXXXXXX | Sleep   |  148 |       | NULL             |
| 58 | application | 192.168.44.1:51968 | XXXXXXXX | Sleep   |   11 |       | NULL             |
| 59 | root        | localhost          | NULL     | Query   |    0 | NULL  | show processlist |
+----+-------------+--------------------+----------+---------+------+-------+------------------+

คุณจะเห็นรายละเอียดทั้งหมดของการเชื่อมต่อที่แตกต่างกัน ตอนนี้คุณสามารถฆ่าการเชื่อมต่อแบบสลีปได้ดังนี้:

mysql> kill 52;
Query OK, 0 rows affected (0.00 sec)

19
นี่ไม่ใช่คำตอบสำหรับคำถาม ที่นี่คุณกำลังฆ่ากระบวนการเดียวในขณะที่คำถามคือคุณจะฆ่ากระบวนการพร้อมกันได้อย่างไร
Hristo Petev

@ badbod99 ฉันลงเอยที่นี่เพื่อค้นหาวิธีการฆ่ากระบวนการ mysql และคำตอบนี้ช่วยฉันได้ดังนั้นฉันจึงโหวตให้
Bogdan

3

สิ่งนี้ใช้งานได้สำหรับฉัน (เซิร์ฟเวอร์ MySQL 5.5) เพื่อฆ่ากระบวนการ MySQL ทั้งหมด:

mysql -e "show full processlist;" -ss | awk '{print "KILL "$1";"}'| mysql

3

ฉันจะรวม bash และ mysql:

for i in $(mysql -Ne "select id from information_schema.processlist where user like 'foo%user' and time > 300;"); do
  mysql -e "kill ${i}"
done

2

นี่คือโซลูชันที่คุณสามารถดำเนินการได้โดยไม่ต้องอาศัยระบบปฏิบัติการ:

ขั้นตอนที่ 1: สร้างขั้นตอนการจัดเก็บ

DROP PROCEDURE IF EXISTS  kill_user_processes$$ 

CREATE PROCEDURE `kill_user_processes`(
  IN user_to_kill VARCHAR(255)
)
READS SQL DATA
BEGIN

  DECLARE name_val VARCHAR(255);
  DECLARE no_more_rows BOOLEAN;
  DECLARE loop_cntr INT DEFAULT 0;
  DECLARE num_rows INT DEFAULT 0;

  DECLARE friends_cur CURSOR FOR
    SELECT CONCAT('KILL ',id,';') FROM information_schema.processlist WHERE USER=user_to_kill;

  DECLARE CONTINUE HANDLER FOR NOT FOUND
    SET no_more_rows = TRUE;

  OPEN friends_cur;
  SELECT FOUND_ROWS() INTO num_rows;

  the_loop: LOOP

    FETCH  friends_cur
    INTO   name_val;

    IF no_more_rows THEN
        CLOSE friends_cur;
        LEAVE the_loop;
    END IF;


 SET @s = name_val;
    PREPARE stmt FROM @s;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    SELECT name_val;

    SET loop_cntr = loop_cntr + 1;

  END LOOP the_loop;

  SELECT num_rows, loop_cntr;

END $$
DELIMITER ;

ขั้นตอนที่ 2: เรียกขั้นตอนการจัดเก็บโดยให้ชื่อของผู้ใช้ฐานข้อมูลที่มีกระบวนการที่คุณต้องการฆ่า คุณสามารถเขียนกระบวนงานที่จัดเก็บใหม่เพื่อกรองเกณฑ์อื่น ๆ ได้หากต้องการ

โทร kill_user_processes('devdba');


2
mysqladmin pr -u 'USERNAME' -p'PASSWORD' | awk '$2~/^[0-9]+/{print $2}' | xargs -i mysqladmin -u 'USERNAME' -p'PASSWORD' kill {}

1
สวัสดี. ไม่แน่ใจว่าคุณเป็นบอทชุมชนหรือมนุษย์ แต่อย่างไรก็ตามจะเป็นการดีหากคุณเพิ่มคำอธิบายว่าเกิดอะไรขึ้นกับโค้ดบรรทัดนี้และจะแก้ปัญหาในมือได้อย่างไร?
Félix Gagnon-Grenier

1
เพิ่ม -u และ -p เพื่อให้เข้าถึงผู้ใช้ ... ได้งานดี!
Lord St John

2

เราสามารถทำได้โดย MySQL Workbench เพียงดำเนินการนี้:

kill id;

ตัวอย่าง:

kill 13412

ที่จะลบมันออก


ฟังดูตอบโจทย์ได้ดีกว่าเนื่องจากไม่มีภาษาที่กล่าวถึงข้างต้น
DeshDeep Singh

0

วิธีง่ายๆคือรีสตาร์ทเซิร์ฟเวอร์ mysql .. เปิด "services.msc" ใน windows Run เลือก Mysql จากรายการ คลิกขวาและหยุดบริการ จากนั้นเริ่มต้นอีกครั้งและกระบวนการทั้งหมดจะถูกฆ่ายกเว้นกระบวนการ (การเชื่อมต่อที่สงวนไว้เริ่มต้น)


0
#! /bin/bash
if [ $# != "1" ];then
    echo "Not enough arguments.";
    echo "Usage: killQueryByDB.sh <db_name>";
    exit;
fi;

DB=${1};
for i in `mysql -u <user> -h localhost ${DB} -p<password> -e "show processlist" | sed 's/\(^[0-9]*\).*/\1/'`; do
    echo "Killing query ${i}";
    mysql -u <user> -h localhost ${DB} -p<password> -e "kill query ${i}";
done;

0

บางครั้งฉันมีกระบวนการ mysql ของซอมบี้ที่ไม่สามารถฆ่าได้ (โดยใช้ MAMP Pro)

ขั้นแรกรับรายการกระบวนการ mysql ทั้งหมด:

ps -ax | grep mysql

จากนั้นฆ่าทุกคนด้วย (แทนที่ processId ด้วยคอลัมน์แรกในผลลัพธ์คำสั่งก่อนหน้า):

kill -9 processId

0

สิ่งต่อไปนี้ใช้ได้ผลดีสำหรับฉัน:

echo "show processlist" | mysql | grep -v ^Id | awk '{print $1}' | xargs -i echo "KILL {}; | mysql"

0

ฉันใช้คำสั่งflush tablesเพื่อฆ่าการเชื่อมต่อที่ไม่ใช้งานทั้งหมดซึ่งเป็นปัญหาที่เกิดขึ้นจริง


1
ไม่ทำงาน ล้างโต๊ะ แต่ยังคงให้ส่วนร่วมการนอนหลับทำงานอยู่
gtryonp

0

สำหรับภาษา python คุณสามารถทำได้เช่นนี้

import pymysql

connection = pymysql.connect(host='localhost',
                             user='root',
                             db='mysql',
                             cursorclass=pymysql.cursors.DictCursor)

with connection.cursor() as cursor:
    cursor.execute('SHOW PROCESSLIST')
    for item in cursor.fetchall():
        if item.get('Time') > 200:
            _id = item.get('Id')
            print('kill %s' % item)
            cursor.execute('kill %s', _id)
    connection.close()

-1

หากคุณใช้ laravel สิ่งนี้เหมาะสำหรับคุณ:

$query = "SHOW FULL PROCESSLIST";
    $results = DB::select(DB::raw($query));

    foreach($results as $result){
        if($result->Command == "Sleep"){
            $sql="KILL ". $result->Id;
            DB::select(DB::raw($sql));
        }
    }

แน่นอนคุณควรใช้สิ่งนี้use Illuminate\Support\Facades\DB;หลังเนมสเปซ


-4

แบบสอบถาม 1 เลือก concat ('KILL', id, ';') จาก information_schema.processlist โดยที่ user = 'username' เป็น outfile '/tmp/a.txt';

Query 2 ที่มา a.txt

สิ่งนี้จะช่วยให้คุณสามารถฆ่าการค้นหาทั้งหมดในรายการกระบวนการแสดงโดยผู้ใช้ที่ระบุ


ฉันโหวตแล้วรู้ว่าคุณเพิ่งคัดลอกคำตอบด้านล่าง rofl; stackoverflow.com/a/21547386/3652863
Robert Pounder

FYI มันเป็นของฉันเอง แต่อะไรก็ได้
Saurav Sood
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.