记一次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 由于公司项目的需要,要在多台服务器上面部署一些应 ...
随机推荐
- MongoDB学习:(二)MongoDB简单使用
MongoDB学习:(二)MongoDB简单使用 MongoDB使用: 执行mongodb的操作之前,我们需要运行命令,来进入操作命令界面 >mongo 提示该错误,说明我们系统缺少一个补丁,该 ...
- APP如何实现推送功能
一.推送功能的集成 (1)在Umeng开发者中心,申请新应用,开通推送功能.此时需要上传开发推送证书和生产推送证书的p12文件. 申请证书的流程如下: >>1 创建开发推送证书 >& ...
- Java C# C语言中的占位符
一般拼接一段字符串在编程中是很常见的事,下面简单做个总结: 什么是占位符?占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号. 1.Java中处理方法: package com.amos; ...
- php版本引起的const问题
刚刚遇到一个问题,类中定义了一个常量: const USER = ['aa', 'bb', 'cc']; 在类中的静态函数中调用以上常量不会出错.网站中所有的网页均能正常打开. 而当push到线上后, ...
- Source Insight 3.X utf8支持插件更新
[更新内容] 修复了当UTF8文件外部改变时,SI无法检测到的bug. 实现 [下载地址] 点我 [计划] 未来(无限长)优化utf8编码检测规则,提高准确度.
- 漫谈Linux内核哈希表(2)
对照前面介绍过的内核通知链.链表,本章我们将要介绍的哈希表的初始化和定义也是如出一辙的: 点击(此处)折叠或打开 定义并初始化一个名为name的哈希链表表头 #define HLIST_HEAD(na ...
- CentOS下MySQL数据库安装
前辈们总是说,要边学边记录,要总结.所以,开始把每天学到的内容一点一点记录. 复杂的理论不懂,只会目前安装,安好后就开始玩咯! 1.在官网下载相应的rpm安装包 下载地址:http://dev.mys ...
- vim的撤销和恢复操作以及匹配当前单词操作
今天顺便看了一下vim的一点命令,记录一下 1.撤销上一次操作和恢复上一次操作: u → undo <C-r> → redo 2.搜索上一个单词和下一个单词 * 和 #: 匹配光标当前所在 ...
- 注册表信息(安装包ProductCode,设置启动运行)
一.获取安装包ProductCode后,再获取安装包DisplayVersion,比对安装包版本,确定是否更新当前应用(重新下载安装包,并运行安装包) //获取当前应用程序的安装包的ProductCo ...
- app之间的跳转,进入二级界面
功能实现:A跳到B并打开B中指定页面.http://blog.csdn.net/dollyyang/article/details/50325307 点击页面判断是否安装app并打开,否则跳转app ...