如何对一个生产系统进行性能的初步诊断,从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(),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+ do #循环判断
set j=j+; #给变量赋值
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(,'Innodb_data_fsyncs'),(,'Innodb_os_log_fsyncs'),(,'Innodb_log_writes'),(,'Innodb_data_writes'),(,'Com_commit'),(,'Com_rollback'),(,'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();
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+ and variable_name=i_name;
#具体的sql语句
update test.pt set c_o_diff=c_variable_value-o_variable_value where id=i_id+ 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