##================================================================##

先来个笑话:

刚交的女朋友让我去他家玩,我觉得空手不好,于是告诉她我买点东西就过去,谁知道她突然来一句:不用买,家里还有一盒!

##================================================================##

昨天在折腾一台磁盘出现性能问题的MySQL时,根据监控去慢日志里找,发现短短10分钟有好几万行慢日志,由于对慢日志结构不熟悉,打开一个600+MB的文件拖着滚动条看,好多慢SQL一条SQL就有几百行,看来看去都没找到问题最根本原因,总算功夫不负有心人,总算在不经意间找到,要不然让我在无知中慢慢老去???

问题SQL如下:

造成的影响:

怀疑造成问题的原因:

由于子查询中没有任何过滤条件,进行全表扫描,而服务器内存不够,导致扫描出来的数据有写到临时文件中,同时服务器上还有其他业务运行,服务器无法及时处理完所有请求,造成积压,而积压请求又增加服务器压力,最终导致相互影响恶性循环。

也不知道研发为啥蛋疼地这么套一下,反正Mysql语句优化处理能力这么差,大家尽可能简化SQL吧

##===================================================##

言归正传,由于这一个SQL执行频率较低,使用pt工具分析不能准确定位到该SQL,而使用肉眼看又比较蛋疼,因此写个小工具来处理,同时还可以解决慢日志较大阅读不便的问题。

python脚本如下:

# coding: utf-8
import datetime
from optparse import OptionParser MAX_QUERY_TIME_SECONDS = 10
START_DATETIME = datetime.datetime.min
END_DATETIME = datetime.datetime.max
SLOW_LOG_PATH = "" class EventInfo(object):
def __init__(self):
self.exec_time = None
self.login_user = ""
self.query_time_seconds = 0
self.lock_time_seconds = 0
self.rows_sent = 0
self.rows_examined = 0
self.command_text = ""
self.file_line_num = 0 def get_datetime_by_time_line(time_line):
if time_line.startswith("# Time:"):
time_str = "" + time_line.replace("# Time:", "").replace(" ", " ").strip()
return datetime.datetime.strptime(time_str, "%Y%m%d %H:%M:%S")
else:
return None def set_query_info(event_info, query_info_line):
line = query_info_line
if line.startswith("# Query_time:"):
tmp_line = line.replace("#", "").replace(": ", ":").replace(" ", " ").replace(" ", " ")
tmp_items = tmp_line.split(" ")
for tmp_item in tmp_items:
# print(tmp_item)
if tmp_item.strip().startswith("Query_time:"):
event_info.query_time_seconds = float(tmp_item.replace("Query_time:", ""))
if tmp_item.strip().startswith("Lock_time:"):
event_info.lock_time_seconds = float(tmp_item.replace("Lock_time:", ""))
if tmp_item.strip().startswith("Rows_sent:"):
event_info.rows_sent = float(tmp_item.replace("Rows_sent:", ""))
if tmp_item.strip().startswith("Rows_examined:"):
event_info.rows_examined = float(tmp_item.replace("Rows_examined:", "")) def set_login_user(event_info, login_user_line):
line = login_user_line
if line.startswith("# User@Host:"):
event_info.login_user = line.replace("# User@Host:", "").strip() def set_command_text(event_info, command_text_line):
line = command_text_line
event_info.command_text += chr(13) + line def print_event_info(event_info):
print_info = """
file_line_num: {7}
Time: {0}
User@Host: {1}
Query_time: {2:.5f} seconds
Lock_time: {3:.5f} seconds
Rows_sent: {4}
Rows_examined: {5}
command_text:
{6}
""".format(event_info.exec_time,
event_info.login_user,
event_info.query_time_seconds,
event_info.lock_time_seconds,
event_info.rows_sent,
event_info.rows_examined,
event_info.command_text,
event_info.file_line_num)
print("*" * 70)
print(print_info) def get_user_paras():
try:
opt = OptionParser()
opt.add_option('--slow_log',
dest='slow_log',
type=str,
help='the file path of the slow log ')
opt.add_option('--long_query_seconds',
dest='long_query_seconds',
type=float,
help='long query seconds')
opt.add_option('--start_datetime',
dest="start_datetime",
type=str,
help="start datetime, format is %Y-%m-%d %H:%M:%S")
opt.add_option('--end_datetime',
dest="end_datetime",
type=str,
help="end datetime, format is %Y-%m-%d %H:%M:%S")
(options, args) = opt.parse_args()
error_messages = []
slow_log = options.slow_log
start_datetime = options.start_datetime
long_query_seconds = options.long_query_seconds
end_datetime = options.end_datetime
if not slow_log:
error_messages.append("slow_log must be set;")
else:
global SLOW_LOG_PATH
SLOW_LOG_PATH = slow_log
if not long_query_seconds:
error_messages.append("long_query_seconds must be set;")
else:
global MAX_QUERY_TIME_SECONDS
MAX_QUERY_TIME_SECONDS = long_query_seconds
try:
if start_datetime is not None:
tmp_start_datetime = datetime.datetime.strptime(start_datetime, "%Y-%m-%d %H:%M:%S")
global START_DATETIME
START_DATETIME = tmp_start_datetime
except:
error_messages.append("the format of start_datetime was wrong ;")
try:
if end_datetime is not None:
tmp_end_datetime = datetime.datetime.strptime(end_datetime, "%Y-%m-%d %H:%M:%S")
global END_DATETIME
END_DATETIME = tmp_end_datetime
except:
error_messages.append("the format of end_datetime was wrong ;") if len(error_messages) > 0:
opt.print_help()
for error_message in error_messages:
print(error_message)
return False
else:
return True
except Exception as ex:
print("exception :{0}".format(str(ex)))
return False def read_log():
global MAX_QUERY_TIME_SECONDS
file_path = SLOW_LOG_PATH
file_handler = open(file_path)
line = file_handler.readline()
line_num = 1
find_event_count = 0
current_event_info = EventInfo()
current_time = ""
has_time = False
while line:
if line.startswith("# Time:"):
current_time = get_datetime_by_time_line(line)
if current_time < START_DATETIME:
line = file_handler.readline()
line_num += 1
continue
if current_time > END_DATETIME:
break line = file_handler.readline()
line_num += 1
has_time = True
continue
if has_time:
if line.startswith("# User@Host:"):
if current_event_info.query_time_seconds > MAX_QUERY_TIME_SECONDS:
print_event_info(event_info=current_event_info)
find_event_count += 1
current_event_info = EventInfo()
current_event_info.file_line_num = line_num
current_event_info.exec_time = current_time
set_login_user(event_info=current_event_info,
login_user_line=line)
elif line.startswith("# Query_time:"):
set_query_info(event_info=current_event_info,
query_info_line=line)
else:
set_command_text(event_info=current_event_info,
command_text_line=line)
line = file_handler.readline()
line_num += 1
print("*" * 70)
print("parse completely")
print("find {0} events".format(find_event_count)) def main():
if get_user_paras():
read_log() if __name__ == '__main__':
main()

脚本调用方式如:

C:\Python27\python.exe D:/GGA/Code/slow_query_find/find_slow_quer.py --slow_log="D:\slow.log.2016010900" --long_query_seconds=4 --start_datetime="2016-01-08 15:46:00" --end_datetime="2016-01-08 15:50:00"

显示结果如:

##==================================================================##

Python--过滤Mysql慢日志的更多相关文章

  1. python mysql开发日志

    开始做python 的数据库访问了,暂时选定了mysql数据库.原本想使用ORM,后来考虑到项目的情况是:表结构不复杂,但是数据库非常大.还是自己来操作sql,不过PYTHON的那些数据库ORM的代码 ...

  2. 使用 python 管理 mysql 开发工具箱 - 1

    Mysql 是一个比较优秀的开源的数据库,很多公司都在使用.作为运维人员,经常做着一些重复性的工作,比如创建数据库实例,数据库备份等,完全都可以使用 python 编写一个工具来实现. 一.模块 Co ...

  3. Python自动化 【第十二篇】:Python进阶-MySQL和ORM

    本节内容 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 创建数据库 外键 增删改查表 权限 事务 索引 python 操作mysql ORM sql ...

  4. Python操作MySQL -即pymysql/SQLAlchemy用法

    本节介绍Python对于MySQL的一些操作用法 模块1:pymysql(等同于MySQLdb) 说明:pymysql与MySQLdb模块的使用基本相同,学会pymysql,使用MySQLdb也就不是 ...

  5. ELK 构建 MySQL 慢日志收集平台详解

    ELK 介绍 ELK 最早是 Elasticsearch(以下简称ES).Logstash.Kibana 三款开源软件的简称,三款软件后来被同一公司收购,并加入了Xpark.Beats等组件,改名为E ...

  6. Python 12 - Mysql & ORM

    本节内容 1.数据库介绍 2.mysql数据库安装使用 3.mysql数据库基础 4.mysql命令 5.事务 6.索引 7.Python操作mysql 8.ORM sqlalchemy了解 数据库介 ...

  7. 前端和后端的数据交互(jquery ajax+python flask+mysql)

    上web课的时候老师布置的一个实验,要求省市连动,基本要求如下: 1.用select选中一个省份. 2.省份数据传送到服务器,服务器从数据库中搜索对应城市信息. 3.将城市信息返回客户,客户用sele ...

  8. logstash采集tomcat日志、mysql错误日志

    input{ file { path => "/opt/Tomcat7.0.28/logs/*.txt" start_position => "beginni ...

  9. python创建MySQL多实例-1

    python创建MySQL多实例-1 前言 什么是多实例 多实例就是允许在同一台机器上创建另外一套不同配置文件的数据库,他们之间是相互独立的,主要有以下特点, 1> 不能同时使用一个端口 2&g ...

  10. ELK构建MySQL慢日志收集平台详解

    上篇文章<中小团队快速构建SQL自动审核系统>我们完成了SQL的自动审核与执行,不仅提高了效率还受到了同事的肯定,心里美滋滋.但关于慢查询的收集及处理也耗费了我们太多的时间和精力,如何在这 ...

随机推荐

  1. mybatis中表与表之间的关联

    第三天 1.mybatis处理表与表之间的关系? 比如要在帖子回复表里显示其它两张相关联表的信息. 处理的第一种方式: 1)主要的数据实体类是ReplyInfo,相关联的实体表的数据是TitleInf ...

  2. 【温故Delphi】Win32API之GetTempFileName

    所遇问题 新建的算量工程文件暂时保存到临时文件中,代码中调用了Win32 API——GetTempFileName 但在一台笔记本上,函数返回了一个空字符串! 为了查明原因想到了好用的GetLastE ...

  3. 通过Guid获取DirectoryEntry对象

    绑定DirectoryEntry对象通常有两种方法,一种是通过字符串(如通过ADsPath),一种是通过Guid(参见:http://msdn.microsoft.com/zh-cn/library/ ...

  4. 原生ajax基础

    /*ajax对象的成员常用属性:responseText:以字符串形式接收服务器端返回的信息responseXML:以Xml Document对象形式接收服务器返回的信息readyState:返回当前 ...

  5. 用C语言关于学生管理系统的几种实现方法(一位数组,二维数组,指针,结构体)

    一位数组: #include <stdio.h> #include<string.h> #define N 5 void luru(float s[],int n); void ...

  6. linux修改主机名的方法

    linux修改主机名的方法 用hostname命令可以临时修改机器名,但机器重新启动之后就会恢复原来的值. #hostname   //查看机器名#hostname -i  //查看本机器名对应的ip ...

  7. 虚拟机安装Ubuntu到U盘

    这篇经验中特指系统安装到U盘,系统在U盘上,不是双系统,不会改变源系统的设置.只需在启动的时候选择启动路径,就可以从U盘启动你的系统.本文仅仅Ubuntu系统,举一反三可以按照此方法安装各种各样的系统 ...

  8. 第51讲:Scala中链式调用风格的实现代码实战及其在Spark编程中的广泛运用

    今天学习了下scala中的链式调用风格的实现,在spark编程中,我们经常会看到如下一段代码: sc.textFile("hdfs://......").flatMap(_.spl ...

  9. Hbase随笔2

    Hbase是建立在HDFS上的分布式数据库,下图是Hbase表的模型: Hbase这个数据库其实和传统关系数据库还是有很多类似之处,而不是像mongodb,memcached以及redis完全脱离了表 ...

  10. Python成长笔记 - 基础篇 (八)

    socket编程 应用层: 表示层: 会话层: 传输层: 网络层: ip地址 数据链路层: MAC地址 物理层:   协议类型: TCP/IP协议:三次握手,四次断开     2. Socket 参数 ...