Python實現MySQL DBA小工具一例

  我們知道MySQL所有的運行狀態統計信息都能從“show global status”語句的結果集中查看,該結果集保存的是從MySQL啓動到當前時間之間各狀態值的“總數”,對我們的分析不友好。在我們日常維護和優化中,我們需要持續的跟蹤某些狀態值的的變化(增量或者是平均值);或者是在調整某些參數後,觀察某些狀態值的變化是否符合我們預期等等。

  基於以上這些需求,作者用Python實現了一個小工具。其實也從“MySQL Workbench”這個圖形化工具中獲得了一點啓發,想到做一個命令行下類似的功能。MySQL Workbench中的dashboard中可顯示如下圖的統計信息,很漂亮哈~

wKiom1dVI53w3a-bAAEnIch64NM659.png

  言歸正傳,該腳本顯示信息的類型分兩類:“指定時間內平均值”和“指定時間內增長值”,在命令選項裏可指定,首先來看一下命令的幫助信息

wKioL1dVESzAV4PTAAPdOsiSzzU823.png

 

  其中--average選項爲查看指定時間平均值,默認查看指定時間內的增長值;-t選項爲想查看的信息類型,每一種信息類型在腳本里對應一個元組(即數組):值爲該類型所包含的“狀態值”。

  這裏我本來想做一個比較完美的命令,大家拿來即用,但是應爲show status裏的狀態值太多了,我不用也沒必要在腳本里包含所有的。腳本里我只將常用的一些信息包含了進來,並且我更傾向於大家把這個腳本看做是一個易於根據自己情況定製的通用框架(其實就是如果自己關心的信息沒有包含在腳本里的話,自己在腳本里添加或修改一個分類即可)。

先看幾個例子

  查看指定時間內qps:

wKiom1dWdK2je-iaAAQzJptSKQU068.png

  查看MySQL網絡相關狀態

wKiom1dVF4PAEl1MAAQGkNEheHE906.png


OK,看完上面截圖覺得這小工具還有點用的,接着看代碼,代碼中註釋還是比較詳細的,只要有點編程基礎,應該是能看的懂的~~

#!/bin/env python3
"""
by lijiankai 20160602
"""

from sys import exit
from time import sleep
from argparse import ArgumentParser,RawTextHelpFormatter
import pymysql

#----------
#定義每種顯示類型(由-t指定)所包含的狀態
#添加和修改要展示的信息修改types_dic字典即可
#同時關注下面add_argument方法添加-t選項時其中choices參數的值,應該和types_dic的鍵一致
#----------
types_dic = {}
types_dic['qps'] = ('Com_select','Com_update','Com_insert','Com_delete','Com_replace','Questions','Queries')
types_dic['table_file'] = ('Opened_tables','Opened_table_definitions','Opened_files','Created_tmp_tables','Created_tmp_disk_tables','Created_tmp_files',)
types_dic['general'] = ('Slow_queries','Select_full_join','Select_full_range_join','Select_range','Select_scan','Sort_range','Sort_rows','Sort_scan')
types_dic['threading'] = ('threads_created')
types_dic['networking_stats'] = ('Bytes_received','Bytes_sent','Connections','Aborted_connects')
types_dic['innodb_buffer_pool'] = ('Innodb_buffer_pool_read_requests','Innodb_buffer_pool_reads','Innodb_buffer_pool_write_requests','Innodb_buffer_pool_wait_free')
types_dic['innodb_data'] = ('Innodb_data_fsyncs','Innodb_data_read','Innodb_data_written') 
types_dic['innodb_stats'] = ('Innodb_log_write_requests','Innodb_log_writes','Innodb_os_log_fsyncs','Innodb_os_log_writes')

#----------
#get_args()函數通過argparse模塊的ArgumentParser類來生成幫助信息並獲取命令行參數
#生成一個全局變量字典對象args,保存處理過的命令行參數
#----------
def get_args():
    #實例化類,formatter_class參數允許help信息以自定義的格式顯示
    parser = ArgumentParser(description="This is a simple tool for MySQL DBA.\nWith this tool you can see several kinds of status's average or increase value in the last N seconds",formatter_class =RawTextHelpFormatter)
    
    #group_necessary = parser.add_argument_group('necessary arguments')
    #group_optional = parser.add_argument_group('optional arguments')    #默認既有該項,所有參數均位於該項下

    parser.add_argument('-u',metavar='USER',dest='user',help="mysql user",required=True)
    parser.add_argument('-p',metavar='PASSWORD',dest='password',help="mysql password",required=True)
    parser.add_argument('-H',metavar='HOSTNAME',dest='host',help="mysql hostname",required=True,)
    parser.add_argument('-P',metavar='PORT',dest='port',help="mysql port(default 3306)",default=3306,type=int)
    parser.add_argument('-i',metavar='INTERVAL_TIME',dest='interval',help="interval time(unit=second,default 10s)",default=10,type=int)
    #--average表示是否查看平均值,默認顯示差值    action不能和metavar共存
    parser.add_argument('--average',dest='average',help='show average value in the interval time(default is the increase value)',action='store_true')    #store_true不能喝metavar共存
    #下面-t選項中的choices的列表值需和腳本開始處定義的types_dic字典的鍵一致
    parser.add_argument('-t',metavar='INFORMATION_TYPE',dest='type',choices=['qps','table_file','general','threading','networking_stats','innodb_buffer_pool','innodb_data','innodb_stats'],help="""information type.See the allowed types below:
qps :   numbers of the DML command executed
table_file :   tables or tmp_tables or tmp_files that are opend or created
general :   something about select
networking_stats :   something about network or connect
innodb_buffer_pool :   something about innodb_buffer_pool stats
innodb_data :   something about innodb_data stats
innodb_stats :   something about innodb stats""",\
    required=True)

    #全局字典 鍵(add_argument()中的dest):值(用戶輸入)
    #vars將Namespace object轉換成dict object
    global args
    args = vars(parser.parse_args())
    #print(args)
    
#----------
#process_query()函數從get_args()返回值中拿到登陸mysql需要的相關信息
#執行show global status語句,並將結果保存在status_dict字典中
#----------
def process_query():
    status_dict={}    #存放所有status值
    try:
        with pymysql.connect(host=args['host'],user=args['user'],password=args['password'],charset='utf8',port=args['port']) as mysql_cur:
            mysql_cur.execute('show global status')    #執行語句,查詢結果的每一行作爲一個元組存進mysql_cur中
    except pymysql.err.MySQLError as err:
        print("ERROR: "+str(err))
        exit(10)

    for status in mysql_cur:
        status_dict[status[0]]=status[1]    #更新status_dict字典
    return status_dict

#----------
#show_result()函數處理相關數據,展示最終結果
#----------
def show_result(type):

    #打印頭部
    print()
    for status in types_dic[args['type']]:
        print('     {}'.format(status),end='')
    print()
    
    #開始循環顯示
    try:
        while True:
            status_dic1=process_query()
            sleep(args['interval'])
            status_dic2=process_query()
            #打印各值
            for k in types_dic[args['type']]:
                if args['average'] is True:
                    #有--average選項,輸出指定時間內的平均值
                    print( '     ' + str(round((int(status_dic2[k])-int(status_dic1[k]))/args['interval'],2)).center(len(k)),end='' )
                else:
                    #輸出指定時間內的增長值
                    print( '     ' + str(round(int(status_dic2[k])-int(status_dic1[k]))).center(len(k)),end='' )
            print()
    except KeyboardInterrupt:
        print('\n-----bye-----')
             
if __name__ == '__main__':
    get_args()
    process_query()
    show_result(args['type'])

最後再囉嗦兩句:

1. 關於MySQL show status中的各狀態,還是建議小夥伴們仔細閱讀下官方文檔的解釋

2. Python編寫命令行工具,用argparse模塊來生成幫助信息和處理命令行參數還是很方便的。


奮進的k博客,原文地址:http://kaifly.blog.51cto.com/3209616/1786586

對這篇文章有任何疑惑或建議都歡迎來討論,一起進步。

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