Python--过滤Mysql慢日志
##================================================================##
先来个笑话:
刚交的女朋友让我去他家玩,我觉得空手不好,于是告诉她我买点东西就过去,谁知道她突然来一句:不用买,家里还有一盒!
##================================================================##
昨天在折腾一台磁盘出现性能问题的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慢日志的更多相关文章
- python mysql开发日志
开始做python 的数据库访问了,暂时选定了mysql数据库.原本想使用ORM,后来考虑到项目的情况是:表结构不复杂,但是数据库非常大.还是自己来操作sql,不过PYTHON的那些数据库ORM的代码 ...
- 使用 python 管理 mysql 开发工具箱 - 1
Mysql 是一个比较优秀的开源的数据库,很多公司都在使用.作为运维人员,经常做着一些重复性的工作,比如创建数据库实例,数据库备份等,完全都可以使用 python 编写一个工具来实现. 一.模块 Co ...
- Python自动化 【第十二篇】:Python进阶-MySQL和ORM
本节内容 数据库介绍 mysql 数据库安装使用 mysql管理 mysql 数据类型 常用mysql命令 创建数据库 外键 增删改查表 权限 事务 索引 python 操作mysql ORM sql ...
- Python操作MySQL -即pymysql/SQLAlchemy用法
本节介绍Python对于MySQL的一些操作用法 模块1:pymysql(等同于MySQLdb) 说明:pymysql与MySQLdb模块的使用基本相同,学会pymysql,使用MySQLdb也就不是 ...
- ELK 构建 MySQL 慢日志收集平台详解
ELK 介绍 ELK 最早是 Elasticsearch(以下简称ES).Logstash.Kibana 三款开源软件的简称,三款软件后来被同一公司收购,并加入了Xpark.Beats等组件,改名为E ...
- Python 12 - Mysql & ORM
本节内容 1.数据库介绍 2.mysql数据库安装使用 3.mysql数据库基础 4.mysql命令 5.事务 6.索引 7.Python操作mysql 8.ORM sqlalchemy了解 数据库介 ...
- 前端和后端的数据交互(jquery ajax+python flask+mysql)
上web课的时候老师布置的一个实验,要求省市连动,基本要求如下: 1.用select选中一个省份. 2.省份数据传送到服务器,服务器从数据库中搜索对应城市信息. 3.将城市信息返回客户,客户用sele ...
- logstash采集tomcat日志、mysql错误日志
input{ file { path => "/opt/Tomcat7.0.28/logs/*.txt" start_position => "beginni ...
- python创建MySQL多实例-1
python创建MySQL多实例-1 前言 什么是多实例 多实例就是允许在同一台机器上创建另外一套不同配置文件的数据库,他们之间是相互独立的,主要有以下特点, 1> 不能同时使用一个端口 2&g ...
- ELK构建MySQL慢日志收集平台详解
上篇文章<中小团队快速构建SQL自动审核系统>我们完成了SQL的自动审核与执行,不仅提高了效率还受到了同事的肯定,心里美滋滋.但关于慢查询的收集及处理也耗费了我们太多的时间和精力,如何在这 ...
随机推荐
- doT.js源码解读
doT.js非常的简洁.全部代码也就200行不到.它的基本思路就是通过强大的正则表达式,把模块转变成可执行的函数,动态生成html字符串.核心new Function(c.varname, str); ...
- Django + Apache + 树莓派 搭建内网微信公众号服务器
其实早在微信开放公众号开发平台时就想弄一个自己的公众号服务器,奈何对web服务器搭建和开发一窍不通,只是注册了一下开发者帐号,并没有采取行动,万恶的拖延症. 前一年,开始接触python,打开了神奇世 ...
- SUSE查看版本号
suse:~ # lsb_release -dDescription: SUSE Linux Enterprise Server 10 (x86_64) suse:~ # cat /etc/SuSE- ...
- js获取新浪天气接口
<!doctype html> <html class="no-js fixed-layout"> <head> <meta charse ...
- WIN2003使用IP安全策略只允许指定IP远程桌面连接
一,新建IP安全策略 WIN+R打开运行对话框,输入gpedit.msc进入组策略编辑器. 依次打开“本地计算机”策略--计算机配置--Windows设置--安全设置--IP安全策略,在 本地计算机上 ...
- Servlet知识
1.Servlet概述 2.编写Servlet的开发步骤a.建立标准的JavaWeb应用目录FirstAppWEB-INFclasseslibweb.xmlb.编写一个类,实现javax.servle ...
- 解决yum报错集
yum -y install gcc gcc-c++ makeError: Multilib version problems found. This often means that the ro ...
- MD5编码
public class MD5 { public static String getMD5(String content) { try { MessageDigest digest = Messag ...
- vs2010的“应用程序向导”新建MFC程序报错“当前页面的脚本发送错误”
原创文章,欢迎阅读,禁止转载. 问题现象不知道从什么时候开始,我的vs2010不能新建MFC程序了,报错如图:... 解决方法根据提示排查,发现是应用程序向导的相关html被损坏了.从同事电脑上把 ...
- 解决Ubuntu下Chrome浏览器网页中文字体混乱
在Ubuntu下使用Chrome浏览器时碰到了网页中文字体混乱的现象: 黑体和楷体混杂,看起来非常不美观. 这是由于许多网页并没有指定字体,然后浏览器将调用系统默认字体配置. 首先,安装文泉驿字体: ...