性能调优-生产问题排查

一、CPU或内存使用率高

1、排查占用CPU的进程

1.1 top命令

  1. 按P键(大写打开时)会按照CPU使用率高低进行排序
  2. 按M键(大写打开时)会按照内存使用率高低进行排序

Top 命令的输出信息主要分为两部分,上半部分显示 CPU 和内存资源的总体使用情况:

1.2 jmap

jmap [options] pid
jmap -histo pid | head -20


1.3 jps

jps [options] [hostid]

option参数

参数

说明

-l

输出主类全名或jar路径

-q

只输出LVMID

-m

输出JVM启动时传递给main()的参数

-v

输出JVM启动时显示指定的JVM参数

其中 [option][hostid] 参数也可以不写。

1.4 常用命令

  1. top:Linux 命令。可以实时查看各个进程的 CPU 使用情况。也可以查看最近一段时间的 CPU 使用情况。默认按 CPU 使用率排序。
  2. ps:Linux 命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前 CPU 使用情况。属于当前状态的采样数据。
  3. jstack:Java 提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。
  4. pstack:Linux 命令。可以查看某个进程的当前线程栈运行情况。
  5. jstat:Java 提供的命令。可以查看某个JVM进程的gc信息。

2、解决问题实战

1、top

进到linux容器中执行 top命令,结果发现高cpu占用,其中pid 为1的正是我们的java程序。

2、top -HP pid

执行命令找出占用CPU最高的线程 top -Hp pid 显示的新pid都是线程,找到占用cpu最高的线程号。

3、printf "%x " tid

把线程号转换为16进制,便于在jstack中查询 printf "%x " tid 变为16进制。

4、jstack pid | grep 0x十六进制结果 -A30

jstack命令查看相应线程的堆栈 jstack pid | grep 0x十六进制结果 -A30

5、jstat -gcutil pid

命令查看进程的堆情况

S0:年轻代中第一个 survivor(幸存区)已使用的占当前容量百分比

S1:年轻代中第二个 survivor(幸存区)已使用的占当前容量百分比

E:年轻代中 Eden 区已使用的占当前容量百分比

O:老年代已使用的占当前容量百分比

M:元数据区使用比例

CCS:压缩使用比例

YGC:从应用程序启动到采样时年轻代中 gc 次数

YGCT:从应用程序启动到采样时年轻代中 gc 所用时间(单位秒)

FGC:从应用程序启动到采样时老年代 full gc 次数

FGCT:从应用程序启动到采样时老年代 full gc 所用时间(单位秒)

GCT:从应用程序启动到采样时 gc 用的总时间(单位秒)

6、jmap -dump:live,format=b,file=pid.hprof pid

命令导出堆文件,只导出 live 存活的对象。文件后缀名可以是任意的,因为它也是二进制的,不过通常以 hprof 结尾。

7、最后使用 JDK 自带的工具,JAVA_HOME/bin/jvisualvm.exe工具分析快照

操作路径:文件 -> 装入 -> 文件类型选择堆,选中刚才导出的堆文件。

选择类列表,按照大小排序,找出占用内存最大的类别

二、数据库CPU使用率100%

1、QPS过高

1.1 首先,查看当前cpu曲线

1.2 发现此时的cpu已经100%,再查看此时的qps曲线

1.3 会发现此时的qps曲线基本和cpu曲线保持一致,此时我们可断定cpu飙升必然存在qps过高的原因。为了验证是否有慢sql的存在,再查看慢sql曲线

发现此案例中完全不存在慢sql。因此责任可100%归为qps过高。

1.4 优化思路

2、慢查询

2.1 首先,查看当前cpu曲线

2.2 然后查看qps曲线

从上图我们可看出,cpu和qps的整体的整体走势是基本一致的,但是上图中相对qps曲线,cpu有好几次的抖动,甚至峰值达到80%,我们需要排查出这些峰刺点。

由于此时的cpu抖动和qps曲线不一致,可推测是慢sql引起的,观察下图抖动时间段内的慢sql,确定是否有慢sql,以及慢sql的具体信息。

观察上图发现该时间段内一些慢sql在库上使得cpu曲线发生了抖动,此时可采取kill+id的方法定制该sql的执行。

2.3 优化思路

考虑表是否设置了合理的索引,表字段是否设置了合理的数据类型,sql是否有效的利用了索引等。

考虑将sql简化,把逻辑操作上浮到业务中去做。

3、解决题实战

3.1 top查看mysql进程号或者ps -ef | grep -i mysql

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                  
16965 mysql     20   0   32.0g   2.8g  16592 S  1566  8.8  49:40.99 mysqld   

3.2 查看CPU使用率最高的线程号

top -Hp 16965

top -p 16965 -H

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                   
17053 mysql     20   0   32.0g   2.8g  16668 R 62.7  9.0   4:47.45 mysqld                                                                                    
17032 mysql     20   0   32.0g   2.8g  16668 R 61.7  9.0   5:03.16 mysqld                                                                                    
17028 mysql     20   0   32.0g   2.8g  16668 R 61.3  9.0   4:38.47 mysqld                                                                                    
17033 mysql     20   0   32.0g   2.8g  16668 R 61.0  9.0   4:56.53 mysqld                                                                                    
17054 mysql     20   0   32.0g   2.8g  16668 R 59.0  9.0   5:17.14 mysqld                                                                                    
17064 mysql     20   0   32.0g   2.8g  16668 R 59.0  9.0   4:57.18 mysqld                                                                                    
17057 mysql     20   0   32.0g   2.8g  16668 R 57.0  9.0   4:47.68 mysqld                                                                                    
17065 mysql     20   0   32.0g   2.8g  16668 R 56.7  9.0   5:00.24 mysqld                                                                                    

可以看到占用最高的是PID=17053

3.3 找到对应的thread_id,processlist_id

mysql> select thread_id,name ,PROCESSLIST_ID,THREAD_OS_ID from performance_schema.threads where thread_os_id = 17053; 
+-----------+---------------------------+----------------+--------------+
| thread_id | name                      | PROCESSLIST_ID | THREAD_OS_ID |
+-----------+---------------------------+----------------+--------------+
|       143 | thread/sql/one_connection |             97 |        17053 |
+-----------+---------------------------+----------------+--------------+
1 row in set (0.00 sec)

3.4 找到当前占用cpu的SQL

select DIGEST_TEXT  from performance_schema.events_statements_current where thread_id = 143 ;

+---------------------------------------------------------------------+
| DIGEST_TEXT
SELECT * FROM t xxx ……

三、补充

1、查看死锁

Mysql 查询是否存在锁表有多种方式,这里只介绍一种最常用的

1、查看正在进行中的事务
SELECT * FROM information_schema.INNODB_TRX

2、查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

3、查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

4、查询是否锁表
SHOW OPEN TABLES where In_use > 0;

5、查看最近死锁的日志
show engine innodb status

2、解除死锁

如果需要解除死锁,有一种最简单粗暴的方式,那就是找到进程id之后,直接干掉。

2.1 查看当前正在进行中的进程

show processlist
SELECT * FROM information_schema.INNODB_TRX;

2.2 杀掉进程对应的进程 id

kill id

2.3 验证(kill后再看是否还有锁)

SHOW OPEN TABLES where In_use > 0;
展开阅读全文

页面更新:2024-04-24

标签:死锁   使用率   百分比   线程   应用程序   曲线   进程   命令   内存   性能   情况

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top