记一次troubleshooting(一):奇慢的脚本
背景:
事情发生的时间是几年前,那时刚从windows server运维的部门调动过来,对linux和数据库还是处于一知半解的状态。
领导找过来说:前任遗留下来的问题你来调查一下,有个客户说他们的日次脚本跑的慢,以前都勉强在运行,现在快要突破允许时间的上限了。
我马上联系了客户,得知是一个mysql的脚本,测试机运行一个半小时左右,业务机却要运行2个半小时多,超过3个小时就会对业务产生影响了。
解决过程:
虽然当时技术方面不是很懂,但是凭大学时电脑城多年售后修电脑的经历,立马祭出了对比排查大法。
|
项目 |
业务机 |
测试机 |
|
硬件 |
4核16GB |
2核4GB |
|
脚本内容 |
SQL |
SQL |
|
数据库存放地点 |
NFS挂载盘 |
本地 |
|
架构 |
Heartbeat,AP/DB双机互为冗余 |
单机 |
|
Mysql配置文件 |
前任优化过了 |
默认配置 |
|
Mysql版本 |
5.5 |
5.6 |
1.硬件
看上去是业务机比测试机强很多,但要说服客户,得讲证据拿出数字来。
于是给两台机器上安装nmon,观察了2个脚本运行周期。
结论是测试机的硬件利用率很高,业务机即使在跑脚本的时候也只用了30%的CPU,50%左右的内存,硬盘IO也只在脚本块结束时才升高。硬件问题基本排除。
2.脚本内容
主要的内容是一条14000多字节的SQL文,直觉告诉我这条SQL文有优化的空间。
但是做过运维的同学都知道,运维—开发—客户这3方往往就是:出了问题客户找开发和运维,运维如果不拿出切实的证据证明是开发的问题开发是不会动的。而且这次开发有一条很好的理由:"测试机脚本运行很快"。
作为测试,开启了mysql的slowquerylog,结果如下
业务机:Count: 1 Time=8947.41s
测试机:Count: 1 Time=3802.91s
虽然一条SQL文运行3800秒也不短,但是比业务机短多了,脚本就算没问题吧。
3.数据库存放地点
NFS因为是有校验机制的,速度肯定是比不过本地硬盘。但是根据nmon的磁盘IO数据,瓶颈肯定不是出在NFS上。但是客户一直在怀疑我们双击热备挂NFS的架构有问题,没办法只能测。
看了一下NFS的服务器,是台windowsstorage的服务器,有Iscsi的功能,于是先不管冗余,把NFS上的数据库文件备份后迁移到Iscsi挂载盘,脚本一跑,除了最后阶段IO有所上升外其他照旧,提升的时间以秒计算。
此路不通,回滚设置。
4.架构
上面说过架构也是客户吐槽点。这个测试简单,备份完数据库后进入crm >resource>move资源到同一台机器上。跑完脚本后问题照旧,客户终于认可了架构不是本次问题的原因。
5.Mysql配置
用MySQLTuner测了一下,配置说实话前任已经优化的差不多了,唯一剩下的一个有可能提升性能的就是innodb_file_per_table参数,试试看吧。
Mysqldump备份数据库,备份ibdata1,ib_logfile0,ib_logfile1文件后删除原文件。删除数据库,设置innodb_file_per_table参数,重启mysql,导入数据库。
一系列工作完成后,脚本一跑,老样子。
6.数据库版本
其实最开始看到数据库版本不一致的时候就想到升级数据库。但是由于工程比较麻烦,而且又没有直接的证据证明是数据库版本的问题,领导和客户都不愿意做。开发又一直觉得不是mysql的问题是硬件/架构/优化的问题。
但是所有怀疑的点都排除后,升级数据库就成了最后可能的手段,而且测试机的mysql5.6一直在运行,说明程序在mysql5.6上是没有问题的,怎样说服领导和客户就成了最大的问题。
于是去mysql官网,翻出了mysql5.6的release note,一页一页的看过去,终于发现了这样一段文字"Semi-Join最適化、FROM句のサブクエリの改善"(日语专精比英语等级高,所以看的日文文档),翻译过来就是"优化了Semi-Join,改善了From文中的子查询"。
马上去数据库测试,结果如下:
Mysql5.5带子查询
mysql> select count(*) from (select * from xxxxx limit 20000) a, (select * from xxxxx limit 20000) b where a.ITEM_CD=b.ITEM_CD;
+----------+
count(*)
+----------+
398624
+----------+
1 row in set (2 min 38.51 sec)
Mysql5.6带子查询
mysql> select count(*) from (select * from xxxxx limit 20000) a, (select * from xxxxx limit 20000) b where a.ITEM_CD=b.ITEM_CD;
+----------+
count(*)
+----------+
398624
+----------+
1 row in set (1.43 sec)
Mysql5.5不带子查询
mysql> select count(*) from xxxxx;
+----------+
count(*)
+----------+
2246654
+----------+
1 row in set (1.15 sec)
Mysql5.6不带子查询
mysql> select count(*) from xxxxx;
+----------+
count(*)
+----------+
2246654
+----------+
1 row in set (1.32 sec)
可以看出,不带子查询的话明显硬件强的业务机(mysql5.5)要快,但是带子查询却是测试机(mysql5.6)要快几十倍,而我们可爱的日次脚本正是查询套子查询套子查询套子查询的结构。证据提出后,客户终于同意升级数据库。
于是跑到IDC,用clonezilla和Acronis启动盘做了两套离线整机备份。然后在休息室里远程备份数据库,打包原来的mysql程序文件扔到角落,源码安装mysql5.6,配置文件什么都已经提前写好,考贝进去开启mysql,导入数据库,跑脚本。
漫长的等待后,抽出slowquerylog一看
Count: 1 Time=1600.18s
终于解决了!业务机硬件发挥出了应该有的水平!虽然1600秒也很长,但这已经远远超出了客户的要求,而且不是运维能解决的事情了。
这个经历的教训和心得:
- 技术是多样的,troubleshooting的方法是共通的
- 永远不要奢望别的公司/部门能帮你扛下担子,可以信任的只有身边的同事和自己
- 一个好的想法必须有数字和证据的支撑
- 百度是个坑,找资料去谷歌
记一次troubleshooting(一):奇慢的脚本的更多相关文章
- 记一个简单的保护if 的sh脚本
真是坑爹,就下面的sh,竟然也写了很久! if [ `pwd` != '/usr/xx/bin/tomcat' ] then echo "rstall is not allowed in c ...
- 线代: N阶行列式
线性变换 将 (x, y) 变成 (2 x + y, x - 3 y) 就叫做线性变换, 这就是矩阵乘法, 用于表示一切线性变换. 几何上看, 把平面上的每个点 (x, y) 都变到 (2 x + y ...
- 恢复训练(学不动了摸会鱼) Pt. 1
本来下午想把pre稿子写了,咕咕咕. 群论是啥也不会了,写个polya试试(手动doge)为什么博客媛没有emoji,以后万一自己搭博客一定要加上这个小东西 polya淼题:poj1286 先复吸一下 ...
- git_sop 脚本使用说明
tags : git 前言 脚本下载地址: git是功能非常强大的版本管理工具,同时它带来的是学习成本的上升.最近我们团队的部分项目采用了git进行版本管理,一部分小伙伴对于git使用不是很熟悉.一方 ...
- pythonxy 安装
安装Numpy,发现错误: No module named msvccompiler in numpy.distutils; trying from distutils 目前python除了在 Win ...
- Kafka如何保证消息不丢失不重复
首先需要思考下边几个问题: 消息丢失是什么造成的,从生产端和消费端两个角度来考虑 消息重复是什么造成的,从生产端和消费端两个角度来考虑 如何保证消息有序 如果保证消息不重不漏,损失的是什么 大概总结下 ...
- pyinstaller模块使用
目前pip install pyinstaller已经成熟 但是还是有一些坑,郁闷了好久,记一下注意点吧. 将py脚本打包成exe文件时,如果导入了非python自带库,则需要将导入的库从site-p ...
- Jmeter(七)Jmeter脚本优化(数据与脚本分离)
午休时间再来记一记,嗯..回顾着使用Jmeter的历程,想着日常都会用到的一些功能.一些组件:敲定了本篇的主题----------是的.脚本优化. 说起脚本优化,为什么要优化?又怎么优化?是个永恒的话 ...
- 使用shell脚本常见的一些问题
Jdk版本:jdk-8u102-linux-x64 Tomcat版本:apache-tomcat-7.0.92 Redis版本:redis-5.0.0 由于公司项目的需要,要在多台服务器上面部署一些应 ...
随机推荐
- js script中引用其他script
在需要引用目标js中引用其他js依赖项 可以使用这个方法直接在js顶部加入这一行即可 document.write("<script type='text/javascript' sr ...
- 使用javascript实现贪吃蛇游戏
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- Android开发学习笔记:浅谈显示Intent和隐式Intent
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://liangruijun.blog.51cto.com/3061169/655132 ...
- js汉语转拼音(全拼、首字母、拼音首字母)
新建js文件first_alphabet.js // JavaScript Document // 汉字拼音首字母列表 本列表包含了20902个汉字,用于配合 ToChineseSpell //函数使 ...
- Windows安装mxnet
code { white-space: pre } div.sourceCode { } table.sourceCode,tr.sourceCode,td.lineNumbers,td.source ...
- tcpdump的使用以及通信协议中常见缩写涵义(持续不定期更新)
1. tcpdump的使用 在tcpdump输出中 Flags: [S],表示该TCP报文段包含SYN标志 [F],表示该TCP报文段包含FIN标志 seq:TCP首部32位序号值 win:接收通告窗 ...
- mac iterm2配置
iterm2的配置分为如下几个部分: 1. 字体大小的配置: iTerm->Preferences->Profiles->Text->Regular Font: 我在这里设置成 ...
- 求两个集合的交集和并集C#
我是用hashset<T>来实现的 具体如代码所示 using System; using System.Collections.Generic; using System.Linq; u ...
- Notepad++列编辑模式
先按住alt,选中列,再上下左右拖动编辑即可:再次点击左键即可取消.
- Hibernate缓存之Aop+cache
在上一篇涉及到查询缓存的功能时除了需要在配置文件中开启缓存外,还需要在业务代码中显示调用setCacheable(boolean)才可以打开查询缓存的功能,这样做,无疑是破坏了封装性,所以就诞生了利用 ...