背景:

事情发生的时间是几年前,那时刚从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秒也很长,但这已经远远超出了客户的要求,而且不是运维能解决的事情了。

这个经历的教训和心得:

  1. 技术是多样的,troubleshooting的方法是共通的
  2. 永远不要奢望别的公司/部门能帮你扛下担子,可以信任的只有身边的同事和自己
  3. 一个好的想法必须有数字和证据的支撑
  4. 百度是个坑,找资料去谷歌

记一次troubleshooting(一):奇慢的脚本的更多相关文章

  1. 记一个简单的保护if 的sh脚本

    真是坑爹,就下面的sh,竟然也写了很久! if [ `pwd` != '/usr/xx/bin/tomcat' ] then echo "rstall is not allowed in c ...

  2. 线代: N阶行列式

    线性变换 将 (x, y) 变成 (2 x + y, x - 3 y) 就叫做线性变换, 这就是矩阵乘法, 用于表示一切线性变换. 几何上看, 把平面上的每个点 (x, y) 都变到 (2 x + y ...

  3. 恢复训练(学不动了摸会鱼) Pt. 1

    本来下午想把pre稿子写了,咕咕咕. 群论是啥也不会了,写个polya试试(手动doge)为什么博客媛没有emoji,以后万一自己搭博客一定要加上这个小东西 polya淼题:poj1286 先复吸一下 ...

  4. git_sop 脚本使用说明

    tags : git 前言 脚本下载地址: git是功能非常强大的版本管理工具,同时它带来的是学习成本的上升.最近我们团队的部分项目采用了git进行版本管理,一部分小伙伴对于git使用不是很熟悉.一方 ...

  5. pythonxy 安装

    安装Numpy,发现错误: No module named msvccompiler in numpy.distutils; trying from distutils 目前python除了在 Win ...

  6. Kafka如何保证消息不丢失不重复

    首先需要思考下边几个问题: 消息丢失是什么造成的,从生产端和消费端两个角度来考虑 消息重复是什么造成的,从生产端和消费端两个角度来考虑 如何保证消息有序 如果保证消息不重不漏,损失的是什么 大概总结下 ...

  7. pyinstaller模块使用

    目前pip install pyinstaller已经成熟 但是还是有一些坑,郁闷了好久,记一下注意点吧. 将py脚本打包成exe文件时,如果导入了非python自带库,则需要将导入的库从site-p ...

  8. Jmeter(七)Jmeter脚本优化(数据与脚本分离)

    午休时间再来记一记,嗯..回顾着使用Jmeter的历程,想着日常都会用到的一些功能.一些组件:敲定了本篇的主题----------是的.脚本优化. 说起脚本优化,为什么要优化?又怎么优化?是个永恒的话 ...

  9. 使用shell脚本常见的一些问题

    Jdk版本:jdk-8u102-linux-x64 Tomcat版本:apache-tomcat-7.0.92 Redis版本:redis-5.0.0 由于公司项目的需要,要在多台服务器上面部署一些应 ...

随机推荐

  1. jQuery Mobile 图标

    jQuery 图标 如需在 jQuery Mobile 中向按钮添加图标,请使用 data-icon 属性: <a href="#anylink" data-role=&qu ...

  2. strstr函数的用法

    C语言函数 编辑 包含文件:string.h 函数名: strstr 函数原型:      extern char *strstr(char *str1, const char *str2); 语法: ...

  3. Oracle 11G在用EXP 导出时,空表不能导出解决

    Oracle 11G在用EXP 导出时,空表不能导出解决 (转)(.http://wanwentao.blog.51cto.com/2406488/545154 11G中有个新特性,当表无数据时,不分 ...

  4. Nginx配置proxy_pass

    nginx配置proxy_pass,需要注意转发的路径配置 1.location /test/ { proxy_pass http://t6:8300; } 2.location /test/ { p ...

  5. asp - Session

    Session[]就是缓存,默认的类型是Object,就是说无论你把什么值赋给Session[],都是会变成Object类型的数据,空说没用,你也别看技术文献里面生涩的解释,我举个例子吧:比如说页面P ...

  6. 关于启动 SecureCRT 遇到一个致命的错误且必须关闭

    --------------------------SecureCRT---------------------------SecureCRT 遇到一个致命的错误且必须关闭. 一个崩溃转储文件已创建于 ...

  7. ReportViewer 不预览,直接导出 PDF文件

    作为笔记记着,以免以后再到处找资料 1. 在不预览的情况下导出文件 先看一个方法说明,想知道ReportViewer支持导出哪些文件类型,在Render方法说明中就有描述 // // Summary: ...

  8. 一个暂时无法理解的bug

    BUG bug的存在是不可避免的 一个静态变量,改成绝对地址之后可以生成静态页面.但是主页有一个用了静态变量的超链接就不能用, 最后我加了一个相对地址的静态变量,可以解决这个问题.

  9. Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)

    思路: dfs序其实是很水的东西.  和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的 ...

  10. Guidelines for accessing OneDrive from an app

    Guidelines for accessing OneDrive from an app https://msdn.microsoft.com/en-us/library/windows/apps/ ...