背景:

事情发生的时间是几年前,那时刚从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. 'autocomplete="off"'在Chrome 中不起作用

    大家都知道autocomplete属性是表单字段中的HTML5新属性,该属性有两种状态值,分别为"on" 和 "off",该属性可省略:省略属性值后默认值为&q ...

  2. jquery each遍历节点使用

    ---恢复内容开始--- $("#aaa :input[type='text']").each(function(i){     alert(this.value); this.v ...

  3. WPF 中使用MVVM模式后,找回ListBox中的ListBoxItem元素

    ListBoxItem lstitem = this.list.ItemContainerGenerator.ContainerFromItem(m) as ListBoxItem; 其中this.l ...

  4. 架​设​W​e​b​服​务​器

    服务器是网站的灵魂,是打开网站的必要载体.按照体系架构来区分,服务器主要分为非X86服务器.x86服务器.非X86服务器使用RISC(精简指令集)或EPIC(并行指令代码)处理器:X86服务器又称CI ...

  5. ebtables hook

    1 概述 netfliter框架不仅仅在ipv4中有应用,bridge,ipv4,ipv6,decnet 这四种协议中都有应用,其中ipv4中又分开了arp和ip的两种 其实netfliter是个大的 ...

  6. Android框架之AndroidAnnotations实战

    方案一: 下载 androidannotations-bundle-3.3.2.zip 方案二:   楼主选用开发环境:android studio 新建项目  修改app 下的build.gradl ...

  7. git conifg

    1. git config简介 我们知道config是配置的意思,那么git config命令就是对git进行一些配置.而配置一般都是写在配置文件里面,那么git的配置文件在哪里呢?互动一下,先问下大 ...

  8. 国际化,java.util.ResourceBundle使用详解

    java.util.ResourceBundle使用详解   一.认识国际化资源文件   这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以:          轻松地本地化或翻译成不同的 ...

  9. [WPF]Slider控件常用方法

    WPF的Slider控件继承自RangeBase类型,同继承自RangeBase的控件还有ProgressBar和ScrollBar,这类控件都是在一定数值范围内表示一个值的用途. 首先注意而Rang ...

  10. div 指令

    div 指令 div 是除法指令,后面跟的是除数,被除数默认在 ax, 或者 dx.ax 组成的存储单元中. 除数可以有 8 位和 16 位两种,存储于一个 reg 或内存单元中,也就是说不可以 di ...