参数优化,iostat详解

如何对一个生产系统进行性能的初步诊断,从OS层面进行IO、CPU、内存、网络IO进行初步诊断。
1.负载在哪个地方
2.瓶颈在哪个地方


iostat 1 -x
这里写图片描述

  • %user:cpu给用户的实际工作时间,图中是16%。
  • %system:系统层面高的话,一般都是I/O过高导致的。
  • %iowait:系统瓶颈。43%的时间在等待,被浪费了。一般>25%就有问题了。
  • %nice和%steal:一般都是0。nice是调整io后的
  • %idle:空闲的时间。一般>25%就认为很好了。
  • rrqm/s:每秒合并的读请求。此值大,说明系统里有严重的全表扫描。
  • wrqm/s:每秒合并的写请求。此值大,说明系统出现严重的批量
  • insert(因为有主键,所以insert的时候很可能由于主键的依次递增而批量insert。insert总是插入相邻的数据块)。
  • r/s:每秒读的次数。
  • w/s:每秒写的次数。 二者相加就是IOPS!
  • rsec/s:每秒读的扇区数。
  • wsec/s:每秒写的扇区数。二者相加就是吞吐量(每秒传输多少M)
  • avgrg-sz:每秒请求扇区的大小。
  • avgqu-sz:平均请求队列的长度。前边排队的请求个数(每次进来后要等待2.85个请求的时间)
  • await:每一个IO请求的处理的平均时间(微秒、毫秒)[即IO的响应时间]。await=avgqu-sz * svctm
  • svctm:平均每次实际的服务时间(毫秒)。
  • %util:繁忙度。在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。

此值高的话,先看IO,如果IO为0或者很低,就找存储工程师,他的硬盘出问题了。如果IO也很高,可能就是操作造成的IO很忙。

PS:avgrq-sz/avgqu-sz/2 –》每个请求扫描多少扇区(单位是KB,因为/2了)


os层面的问题:

  • IO繁忙
  • 写繁忙:svctm
    • ①降低IO:日志写、page写
    • ②提升io性能(主要是写功能)(闪卡、raid卡)
  • 与写功能相关的状态值
    • status
    • write
    • log(redo log、binlog)
    • flush
    • fsync
    • 【监控项:flush、write、fsync(绕过系统缓存,直接fsyncs)、innodb_flush_log_at_trx_commit(0,1,2)】
  • 变量variables
    • 事务提交相关
    • binlog相关
  • redo log size、redo log buffer
  • 脏数据大小、比例
    • innodb_max_dirty_pages_pct=75

优化的分类:

  • ①参数优化
  • ②索引优化
  • ③SQL优化
  • ④分库分表分区优化

参数优化

  • 1.从OS层面查看系统目前的负载点和性能瓶颈。
    • 负载点主要在写上。
    • 性能的瓶颈点,也主要在写上。
  • 2.从数据库层面分析一下,负载点主要在数据库的哪些组件上。
    • show global status,查询 GLOBAL_STATUS表
  • 3.调整哪些参数可以提升对应的性能。
  • 4.调整参数,压力测试,看一下效果。

=====步骤
1.tpcc压力测试的同时iostat 1 -x。发现,读少,写多。系统的写压力很大。
2.mysql层面监控一下,这些写压力都来自于哪些组件。(日志写,page写)
这里写图片描述

  • data page、log、double write #有这些写
  • show global stataus like ”; 或者查询GLOBAL_STATUS表(所有的状态值都在这个表里,大部分是累计值。)

3.调整参数,持续监控
1)调整显然可以提升性能的参数。
如果这个参数的特点是:开、关,调整就很简单。
如果这个参数是一个数值,就需要逐步调整,持续监控。
2)持续观察INNODB_LOG_WRITES


参数优化的思路

  • 1.OS层面查看我们系统的性能瓶颈点和负载点

这里写图片描述

发现,读少,写多。系统的写压力很大。

  • 2.写负载过大,来调整一下写负载,让写负载降低下来

(1)首先关闭double write,这个是基本常识,不需要性能监控。
会发现,写负载明显降低。
这里写图片描述

TPS也从160明显提升到200~300:

这里写图片描述

(2)调整了文件系统的mount参数,这个也属于常规调整。
这里写图片描述

(3)持续观察fsync,记录变化前的基本值。

pager grep -i "fsync";

innodb_data_fsyncs 大约在220/10 秒
innodb_os_log_fsyn 大约在110/10 秒

调整参数:
这里写图片描述

系统启动以后,需要持续观察fsync的变化量,在观察fsync以前,发现系统的写性能明显降低:

这里写图片描述

TPS也明显降低:
这里写图片描述

结论:在这个版本的Linux和MySQL下,下面的参数不能再调整:

show variables like ‘%method%’;
这里写图片描述

绘制性能趋势图:
这里写图片描述

从上图可见,波峰波谷还是比较明显的。

调整参数 innodb_log_file_size
重启数据库,将redo log 从50M调整成300M:

这里写图片描述

性能明显提升:
这里写图片描述

调整参数以前一定关注状态值,这俩可能会影响数据的完整性
1,1性能最佳,调整之后,看一下变化趋势
另外调整一下iocapacity、lru scan depth

调完之后监控log write,fsync
这里写图片描述

  • 3、提升写性能
    • Raid卡
    • 闪卡

存储过程

eg:把一些状态值每隔2s抽出来放到一张表中:

create table test.pt( id int,variable_name varchar(20),c_variable_value int,o_variable_value int,c_o_diff int) engine memory;   
#每抽一次,id加一;要抽的变量名;变量当前的值;变量上一个值;差值;引擎用memory

delimiter //    #以//标志作为存储过程的结束
create procedure do_insert_pt(i int,k int)
begin   #begin...end是一对,是存储过程的开头和结尾
declare j int default 1;    #定义变量
while j<i+1 do      #循环判断
set j=j+1;      #给变量赋值
select sleep(k);
insert into test.pt(id,variable_name,c_variable_value) select j,VARIABLE_NAME,VARIABLE_VALUE from information_schema.global_status where VARIABLE_NAME in (select c_name from pt_c);        
#执行SQL。对select来说,取出来的数字赋给一个变量或者游标。插入/删除是直接执行的
end while;  #结束循环
end;        #与begin...end是一对
//      #存储过程结束

insert into pt_c values(1,'Innodb_data_fsyncs'),(2,'Innodb_os_log_fsyncs'),(3,'Innodb_log_writes'),(4,'Innodb_data_writes'),(5,'Com_commit'),(6,'Com_rollback'),(7,'Innodb_buffer_pool_pages_flushed');


delimiter //
create procedure do_update_pt(i int,j int)
begin
DECLARE done INT DEFAULT FALSE; #定义一个变量叫done
declare i_id int;   
declare i_name varchar(30);
declare i_c_variable_value int;
DECLARE c_1 CURSOR FOR SELECT id,variable_name,c_variable_value FROM test.pt where id between i and j order by id,variable_name;
#定义一个游标。这个游标是select对应的一个结果集
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
#for not found意思就是取到最后,没有数据了,就让done=ture。
open c_1;       #打开游标
read_loop: loop
fetch c_1 into i_id,i_name,i_c_variable_value;  
#把结果集的第一行拿出来,分别赋值给三个变量
  IF done THEN
      LEAVE read_loop;
    END IF;
update test.pt set o_variable_value=i_c_variable_value where id=i_id+1 and variable_name=i_name;
#具体的sql语句
update test.pt set c_o_diff=c_variable_value-o_variable_value where id=i_id+1 and variable_name=i_name;
#具体的sql语句
end loop;
close c_1;
end;
//
show index from pt;
+-------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| pt    |          1 | i_pt     |            1 | id            | NULL      |        NULL |     NULL | NULL   | YES  | HASH       |         |               |
| pt    |          1 | i_pt     |            2 | variable_name | NULL      |         777 |     NULL | NULL   | YES  | HASH       |         |               |
+-------+------------+----------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
create index i_pt on pt(id,variable_name);

select c_o_diff from pt where variable_name='INNODB_LOG_WRITES';
  • 1、要分析为什么要调整这些参数值
  • 2、修改一个参数、观察状态值、继续调整、直至效果最佳

Create By LPeng

posted @ 2017-12-08 22:54  斯言甚善  阅读(495)  评论(0编辑  收藏  举报