python練手腳本-自動結束mysql慢查詢會話

背景

生產環境的有些sql查詢寫得太複雜,或是表很大,對應索引未建立或建立不合理,或是查詢未充分使用索引等,就有可能出現慢查詢,一些慢查詢需要修改程序,可能沒那麼快能解決,這時如果有個腳本能自動檢測符合條件的慢查詢會話並結束,那麼是很方便的,當然運維人員也可順便弄個檢測慢查詢並告警的腳本。

涉及知識點

  1. mysql慢查詢會話查詢
  2. schedule定時任務調度
  3. pymysql執行sql

代碼分解

mysql慢查詢

#會話查詢,只能查詢所有會話,不能按條件過濾,不過比較好記
show PROCESSLIST;

#從information_schema中查詢會話,可以按條件過濾
SELECT
	*
FROM
	information_schema.`PROCESSLIST`;

#查詢符合條件的慢會話,id是會話ID,info是正在執行的sql,time是會話持續時間,殺會話時注意要做好過濾
SELECT
	id,
	info,
	time
FROM
	information_schema.`PROCESSLIST`
WHERE
	info LIKE '%select * from table%'
AND time > 10;

#直接使用sql批量殺會話,拼接kill xxx;後,拷貝了在控制檯執行
SELECT
	concat('KILL ', id, ';')
FROM
	information_schema.`PROCESSLIST`
WHERE
	info LIKE '%select * from table%'
AND time > 10;
腳本主入口
if __name__ == '__main__':
    #每5秒執行檢查任務
    schedule.every(5).seconds.do(kill_slow)
    #此處固定寫法,意思是每秒鐘schedule看下是否有pending的任務,有就執行
    while True:
        schedule.run_pending()
        time.sleep(1)
schedule的其它示例
import schedule
import time

def job(message='stuff'):
    print("I'm working on:", message)

#每10分鐘
schedule.every(10).minutes.do(job)
#每小時
schedule.every().hour.do(job, message='things')
#每天10點30分
schedule.every().day.at("10:30").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)
pymysql使用
# 連接數據庫,設置結果集用dict返回,autocommit自動提交事務
db = pymysql.connect(host='localhost', db='dbname',
                     user='root', passwd='admin',
                     port=3306, charset='utf8',
                     cursorclass=pymysql.cursors.DictCursor, autocommit=True)
cursor = db.cursor()
查詢符合條件的慢會話並結束
def kill_slow():
    cursor.execute(
        """
        SELECT
            id,
            info,
            time
        FROM
            information_schema.`PROCESSLIST`
        WHERE
            info LIKE '%select * from table%'
        AND time > 10;
        """)
    slow_sessions = cursor.fetchall()
    for slow_session in slow_sessions:
        print("slow session detected, kill it:\n id:%s\nsql:%s" % (
            slow_session[0], slow_session[1]))
        cursor.execute("kill %s", slow_session[0])

完整代碼

import time

import pymysql
import schedule

# 連接數據庫,設置結果集用dict返回,autocommit自動提交事務
db = pymysql.connect(host='localhost', db='dbname',
                     user='root', passwd='admin',
                     port=3306, charset='utf8',
                     cursorclass=pymysql.cursors.DictCursor, autocommit=True)
cursor = db.cursor()


def kill_slow():
    cursor.execute(
        """
        SELECT
            id,
            info,
            time
        FROM
            information_schema.`PROCESSLIST`
        WHERE
            info LIKE '%select * from table%'
        AND time > 10;
        """)
    slow_sessions = cursor.fetchall()
    for slow_session in slow_sessions:
        print("slow session detected, kill it:\n id:%s\nsql:%s" % (
            slow_session["id"], slow_session["info"]))
        cursor.execute("kill %s", slow_session["id"])


if __name__ == '__main__':
    # 每5秒執行檢查任務
    schedule.every(5).seconds.do(kill_slow)
    # 此處固定寫法,意思是每秒鐘schedule看下是否有pending的任務,有就執行
    while True:
        schedule.run_pending()
        time.sleep(1)

資料下載

關注公衆號:零壹視界,回覆關鍵詞:python,可免費獲取python經典學習資料。
零壹視界 wechat掃描關注我的微信公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章