分析Mysql慢日志脚本及快速定位慢Sql

分析Mysql慢日志是运维工作中,不可少的。要快速定位慢Sql,以及发现后优化Sql及修改业务,保证数据库稳定高效地工作。下面是我工作中解决的思路...

1.先查看本地数据库慢日志文件


2.编写分析慢日志脚本

#!/usr/bin/python
#coding=utf-8  #字符编码
import re  #导入正则匹配模块
import time #导入时间模块
import sys  #导入sys模块
import MySQLdb #导入连接mysql模块
canshu=len(sys.argv) #参数个数
def help():
    #帮助函数
    print "分析当天慢日志执行命令python %s today today" %sys.argv[0]
    print "分析以前慢日志执行命令python %s before 日志名字" %sys.argv[0]
def create_table():
    # 打开数据库连接
    db=MySQLdb.connect("192.168.1.1","test","test","log_fenxi")
    # 使用cursor()方法获取操作游标
    cursor=db.cursor()
    # 如果数据表已经存在使用 execute() 方法删除表。
    cursor.execute("DROP TABLE IF EXISTS `mysql_slow`;")
    # 创建数据表SQL语句
    sql="""CREATE TABLE `mysql_slow` (
      `id` int(11)  unsigned NOT NULL AUTO_INCREMENT,
      `Query_time` float(11,6) NOT NULL,
      `Lock_time` char(11) NOT NULL,
      `Rows_sent` int(11) NOT NULL,
      `Rows_examined` int(11) NOT NULL,
      `time` datetime NOT NULL,
      `slow_sql` text NOT NULL,
       PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"""
    cursor.execute(sql)
    # 关闭数据库连接
    db.close()
def insert_table():
    log_file=open(log_name) #读取慢日志
    # 打开数据库连接
    db=MySQLdb.connect("192.168.1.1","test","test","log_fenxi")
    # 使用cursor()方法获取操作游标
    cursor = db.cursor()
    for line in log_file:
        line=line.strip()
        Query_time=re.search(‘Query_time:(\s\d+\.\d+)‘,line) #正则匹配慢日志时间
        Lock_time=re.search(‘Lock_time:(\s\d+\.\d+)‘,line)   #正则匹配锁定时间
        Rows_sent=re.search(‘Rows_sent:(\s\d+)‘,line)    #正则匹配返回结果好多行数据
        Rows_examined=re.search(‘Rows_examined:(\s\d+)‘,line)   #正则匹配扫描好多行数据
        timestamp=re.search(‘timestamp=(\d+)‘,line)   #正则匹配时间戳
        slow_sql=re.match(‘(SELECT.*?);‘,line)   #正则匹配慢sql
        if Query_time:
           Query_time_new=Query_time.group(1).strip()  #匹配正则结果赋值
        if Lock_time:
           Lock_time_new=Lock_time.group(1).strip()  #匹配正则结果赋值
        if Rows_sent:
           Rows_sent_new=Rows_sent.group(1).strip()  #匹配正则结果赋值
        if Rows_examined:
           Rows_examined_new=Rows_examined.group(1).strip()  #匹配正则结果赋值
        if timestamp:
           timestamp=int(timestamp.group(1))
           timeArray=time.localtime(timestamp)
           sql_time=time.strftime("%Y-%m-%d %H:%M:%S", timeArray)  #匹配正则结果赋值
        if slow_sql:
            slow_sql_new=slow_sql.group()  #匹配正则结果赋值
            # SQL 插入语句
            sql = """INSERT INTO mysql_slow(Query_time,Lock_time,Rows_sent,Rows_examined,time,slow_sql)
                VALUES ("""+Query_time_new+""","""+Lock_time_new+""","""+Rows_sent_new+""","""+Rows_examined_new+""",‘"""+sql_time+"""‘,‘"""+slow_sql_new+"""‘)""";
            try:
               # 执行sql语句
               cursor.execute(sql)
               # 提交到数据库执行
               db.commit()
            except:
               # Rollback in case there is any error
               db.rollback()
    log_file.close()
    # 关闭数据库连接
    db.close()
def main():
    global log_name
    if canshu!=3:
       print "参数数量错误,请检查!"
       help()
    else:
       create_table()
       xuanze=sys.argv[1]   #第一个参数(慢日志时间)
       log_before=sys.argv[2] #慢日志具体时间 
       if xuanze==‘today‘:
            log_name=‘/data/mysqlp/mysql-slow.log‘
            insert_table()
       elif xuanze==‘before‘:
            log_name=‘/data/logs/mysql_slow/%s‘ %log_before
            insert_table()
       else:
            print ‘参数类型选择错误,类型只包含today|before‘
            help()
main()

3.用脚本处理的结果存在数据库中,查看数据库记录。


备注:

  如果想快速定位那些Sql有问题,只需要把Query_time和Rows_examined字段进行降序排序就可以定位了。可以把排序在前面的Sql手动进行查询,如果发现还是比较慢就需要优化Sql和修改业务了。

  如果想用此脚本直接使用,需要修改数据库连接ip和用户密码,还需要在日志库上面安装MySQLdb模块,并且需要修改当前慢日志路径及名字/data/mysqlp/mysql-slow.log,及保留慢日志的路径/data/logs/mysql_slow,这两个路径请根据自己存储路径修改,才能正常使用此脚本!

本文出自 “成都@阿状” 博客,请务必保留此出处http://azhuang.blog.51cto.com/9176790/1561517

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。