14

mysql性能专题分析 -m6米乐安卓版下载

原创 黄超 2022-06-21
2520

1.问题排查

1)通过top命令确认是否是mysqld进程占用过高cpu

#top
tasks: 102 total,   1 running, 101 sleeping,   0 stopped,   0 zombie
%cpu(s):  90.0 us,  9.0 sy,  0.0 ni, 89.4 id,  0.5 wa,  0.0 hi,  0.0 si,  0.0 st
kib mem :  1867048 total,   397904 free,  1219676 used,   249468 buff/cache
kib swap:  2097148 total,  2097148 free,        0 used.   462424 avail mem 
   pid user      pr  ni    virt    res    shr s  %cpu %mem     time  command                                                                                              
  1821 mysql     20   0 12.327g 1.075g  12004 s  375 60.4   0:13.96 mysqld                                                                                               
    32 root      39  19       0      0      0 s   8.6  0.0   0:00.65 khugepaged                                                                                           
    12 root      rt   0       0      0      0 s   0.7  0.0   0:00.02 migration/1                                                                                          
    46 root      20   0       0      0      0 s   0.7  0.0   0:00.16 kworker/0:2                                                                                          
     1 root      20   0  193700   6820   4044 s   0.0  0.4   0:00.91 systemd                                                                                              
     2 root      20   0       0      0      0 s   0.0  0.0   0:00.00 kthreadd

2)查看cpu飙高的mysql线程,top -h -p

#top -h -p 1821
top - 21:04:24 up 10 min,  1 user,  load average: 0.00, 0.02, 0.04
threads:  31 total,   0 running,  31 sleeping,   0 stopped,   0 zombie
%cpu(s):  90.0 us,  0.2 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
kib mem :  1867048 total,   390212 free,  1227176 used,   249660 buff/cache
kib swap:  2097148 total,  2097148 free,        0 used.   454824 avail mem 
   pid user      pr  ni    virt    res    shr s %cpu %mem     time  command                                                                                               
  1942 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:00.26 mysqld                                                                                                
  1821 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:13.02 mysqld                                                                                                
  1924 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:00.00 mysqld                                                                                                
  1927 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:00.01 mysqld                                                                                                
  1928 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:00.02 mysqld                                                                                                
  1929 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:00.01 mysqld                                                                                                
  1930 mysql     20   0 12.327g 1.082g  12004 s  90 60.8   0:00.02 mysqld

3)根据具体pid,定位问题sql

mysql>select a.thread_os_id,b.id,b.user,b.host,b.db,b.command,b.time,b.state,b.info
from performance_schema.threads a,information_schema.processlist b
where b.id = a.processlist_id and a.thread_os_id=<具体pid>;

2.问题处理

cpu使用率过高最常见场景的处理方法

1)sql执行成本高,sql运行时间长,大事务

show processlist:命令的输出结果显示了有哪些线程在运行,可以帮助识别出有问题的sql语句
实时运行中的sql里面超过10秒的按时间倒序列出,定位运行时间长sql:

mysql>select * from information_schema.processlist where command != 'sleep'  and time >10 order by time desc;

这些运行时间长的sql需要优化,比如适当建立某字段的索引。

线上环境,紧急时候,可以 kill 会话:
通过information_schema.processlist表中的连接信息生成需要处理掉的mysql连接的语句临时文件,然后执行临时文件中生成的指令

mysql>select concat('kill ',id,';') from information_schema.processlist where time>10  and db is not null and command!='sleep' into outfile '/tmp/a.txt';
query ok, 2 rows affected (0.00 sec)
mysql>source  /tmp/a.txt;
query ok, 0 rows affected (0.00 sec)

2)跑批任务,并发高

联系应用人员,看这些会话都是在干啥的,问他们能不能杀或者停掉任务。
杀掉指定用户运行的连接,例如这里为usera

#mysqladmin -uroot -p processlist|awk -f "|" '{if($3 == "usera")print $2}'|xargs -n 1 mysqladmin -uroot -p kill

3.建议与总结

1)升级实例规格,增加 cpu 资源
2)跑批任务,建议在业务低谷定时执行,以免影响线上业务
3)show processlist实时查看执行时间过长的sql,优化这些sql
4)打开慢查询日志,针对慢sql ,explain分析执行计划,优化改进
5)定期分析表,使用optimize table,整理碎片,回收空间
6)开启查询缓存或者使用缓存产品,减轻实例压力
7)考虑读写分离,增加只读库
8)定期归档历史数据、采用分库分表或者分区的方式减小查询访问的数据量

1.问题排查

1)查看系统内存

#free -m
total        used        free      shared  buff/cache   available
mem:      49152     5898         242           8         250         310
swap:          2047           0        2047

2)查看mysqld进程占用系统内存情况

#top
pid user pr ni virt res shr s %cpu %mem time  command
3018 mysql 20 0 44.2g 41g 4232 s 0.0 86.8 981:52.36 mysqld

3)计算mysql当前配置最大的内存消耗

mysql>select (
@@key_buffer_size  
@@table_open_cache  
@@innodb_buffer_pool_size  
@@innodb_log_buffer_size  
@@max_connections * (  
@@read_buffer_size  
@@read_rnd_buffer_size  
@@sort_buffer_size  
@@join_buffer_size  
@@binlog_cache_size  
@@tmp_table_size  
@@thread_stack ) ) /
(1024 * 1024 * 1024) as max_memory_gb;

sys 模式查询通过 current_alloc() 代码区域聚合当前分配的内存:

mysql> select substring_index(event_name,'/',2) as
       code_area, sys.format_bytes(sum(current_alloc))
       as current_alloc
       from sys.x$memory_global_by_current_bytes
       group by substring_index(event_name,'/',2)
       order by sum(current_alloc) desc;

performance_schema下的几个表跟内存相关:
memory_summary_by_account_by_event_name
memory_summary_by_host_by_event_name
memory_summary_by_thread_by_event_name
memory_summary_by_user_by_event_name
memory_summary_global_by_event_name

2.问题处理

内存占用过高最常见场景的处理方法

1)参数配置有误

mysql的配置参数中,有的是配置全局的内存使用大小,有的是配置单个线程的内存大小。
全局内存:
innodb_buffer_pool_size:缓冲池大小
innodb_log_buffer_size:重做日志缓存大小
key_buffer_size:索引缓冲区的大小,只用于myisam引擎
线程内存:
read_buffer_size:顺序读缓存大小
read_rnd_buffer_size:随机读缓存大小
sort_buffer_size:排序缓存大小
join_buffer_size:join联接缓存大小
tmp_table_size:临时表缓存大小
max_connections:最大连接数

a)innodb_buffer_pool_size设置过大

innodb_buffer_pool_size设置过大,会占用太多内存,修改innodb_buffer_pool_size的值,可以减少内存占用。
例如,系统8g 内存,设置mysql缓冲池为4g

mysql> set global innodb_buffer_pool_size=4*1024*1024*1024;
    query ok, 0 rows affected (0.10 sec)
mysql> select @@innodb_buffer_pool_size;
 --------------------------- 
| @@innodb_buffer_pool_size |
 --------------------------- 
|                4294967296 |
 --------------------------- 
1 row in set (0.00 sec)

在线动态修改生效,重启mysql 后修改会丢失,若是想修改的永久有效,需要编辑my.cnf

b)线程内存参数设置过大

线程内存参数是单个线程所占用大小,乘以连接数,得到所占用内存。并发高,连接多,会占用非常大的内存。
例如,sort_buffer_size是一个connection级参数,在每个connection第一次需要使用这个buffer的时候,一次性分配设置的内存。并不是越大越好,由于是connection级的参数,过大的设置 高并发可能会耗尽系统内存资源。官方文档推荐范围为256kb~2mb。

mysql> set global sort_buffer_size=2*1024*1024;

2)table cache相关的内存占用大

业务低峰时清空所有表的缓存或者降低table_open_cache的值

mysql >flush tables;

3)存在session过多

如果空闲session过多,可以kill掉

mysql> select concat('kill ', id, ';') from information_schema.processlist 
where command = 'sleep' into outfile '/tmp/a.txt';
query ok rows, 2 affected (0.00 sec)
mysql>source  /tmp/a.txt;
query ok, 0 rows affected (0.00 sec)

3.建议与总结

1)增大内存,合理分配内存
2)减少创建临时表、sort或join等操作
3)释放操作系统内存 echo 1 >/proc/sys/vm/drop_caches
4)重启mysql(生产环境谨慎操作),释放内存。若是实例是双机环境下的主库,需要先切换为从库

1.问题排查

1)用iostat监测到的io利用率过高

#iostat -k -d -x 1 10
device:         rrqm/s   wrqm/s     r/s     w/s    rkb/s    wkb/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00   83.00     0.00   650.50    15.67     2.55   30.66    0.00   30.66  12.02  99.80
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00   83.00     0.00   636.50    15.34     2.55   30.66    0.00   30.66  12.02  99.80
device:         rrqm/s   wrqm/s     r/s     w/s    rkb/s    wkb/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00   88.00     0.00   684.50    15.56     2.60   29.42    0.00   29.42  11.35  99.90
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00   87.00     0.00   677.00    15.56     2.60   29.76    0.00   29.76  11.49 100.00
device:         rrqm/s   wrqm/s     r/s     w/s    rkb/s    wkb/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00   87.00     0.00   687.50    15.80     2.48   28.77    0.00   28.77  11.51 100.10
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00   88.00     0.00   699.00    15.89     2.48   28.48    0.00   28.48  11.36 100.00
device:         rrqm/s   wrqm/s     r/s     w/s    rkb/s    wkb/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00   88.00     0.00   756.50    17.19     2.48   28.22    0.00   28.22  11.35  99.90
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00   86.00     0.00   740.00    17.21     2.48   28.87    0.00   28.87  11.62  99.90 

2)通过iotop工具可以看到当前io消耗最高的mysql线程

 #iotop
total disk read :       0.00 b/s | total disk write :     683.85 k/s
actual disk read:       0.00 b/s | actual disk write:     721.19 k/s
tid  prio  user     disk read  disk write  swapin     io>    command                                                        
 7061 be/4 mysql       0.00 b/s  153.28 k/s  0.00 % 72.27 % mysqld --defaults-file=/etc/mysq~mysql/3306 mysql.sock --port=3306

2.问题处理

io过高最常见场景的处理方法

1)mysql的各种日志刷盘频繁

可以修改以下mysql参数
innodb_flush_log_at_trx_commit=2(值0,性能最好;主库为了数据一致性,一般值为1,速度最慢)
sync_binlog=1000((值0,性能最好;值1,最慢)
例如,修改innodb_flush_log_at_trx_commit值

mysql> set global innodb_flush_log_at_trx_commit=2;
query ok, 0 rows affected (0.00 sec)
mysql> show variables like ' innodb_flush_log_at_trx_commit ';
 -------------------------------- ------- 
| variable_name                  | value |
 -------------------------------- ------- 
| innodb_flush_log_at_trx_commit     | 2     |
 -------------------------------- ------- 
2 rows in set (0.00 sec)
mysql> show variables like '%sync_binlog%';
 --------------- ------- 
| variable_name | value |
 --------------- ------- 
| sync_binlog   | 1     |
 --------------- ------- 
1 row in set (0.01 sec)
mysql> set global sync_binlog=1000;
query ok, 0 rows affected (0.00 sec)

2)数据批量更新插入写盘

修改mysql参数:

innodb_write_io_threads=8(根据机器核数修改)
innodb_io_capacity=2000 (ssd盘改大)

mysql> set global  innodb_write_io_threads =8;
mysql> set global  innodb_io_capacity =2000;

3)临时表刷盘

一些有问题的sql语句生成了较大的临时表,内存放不下,于是全部刷到磁盘,导致io飙升,可以增大tmp_table_size值

mysql> set global  tmp_table_size=512*1024*1024; 

3.建议与总结

1)选用性能好的ssd磁盘
2) 增大内存,缓存足够大,减少物理io
3)根据数据重要程度,选择适合的日志刷盘方式。
4)单条insert语句优化为批量insert语句,减少事务commit次数
5)优化sql,减少产生临时表,优化索引。

最后修改时间:2022-06-21 23:06:07
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
1人已赞赏
【米乐app官网下载的版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论

网站地图