CPU使用率飙升

使用 jdk 自带的命令 jstack

1
2
3
4
5
6
7
1.top // 查看所有进程的CPU使用率

2.top -Hp PID // 查看某个进程内的线程的CPU使用率

3.printf '%x\n' TID // 查看线程ID对应的16进制数

4.jstack PID | grep -A 200 TID(16进制)

使用 Alibaba 的 arthas

代码死锁

使用 jdk 自带的命令 jstack

image-20240229093510071

模拟的死锁代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class DeadLock {

private static final Object obj1 = new Object();
private static final Object obj2 = new Object();

public static void main(String[] args) {
Thread t1 = new Thread(new MyTask(true), "thread-1");
Thread t2 = new Thread(new MyTask(false), "thread-2");
t1.start();
t2.start();
}

static class MyTask implements Runnable{

private boolean flag;

public MyTask(boolean flag) {
this.flag = flag;
}

@Override
public void run() {
if(flag){
synchronized (obj1){
System.out.println(Thread.currentThread().getName() + "obj1");
synchronized (obj2){
System.out.println(Thread.currentThread().getName() + "obj2");
}
}
}else {
synchronized (obj2){
System.out.println(Thread.currentThread().getName() + "obj2");
synchronized (obj1){
System.out.println(Thread.currentThread().getName() + "obj1");
}
}
}
}
}
}

数据库死锁

使用 show engine innodb status 查看死锁日志

出现死锁的原因一般是循环等待条件满足了

对于索引加锁,如果只有主键索引,那么直接在主键索引上加锁;如果还有二级索引,那么先在二级索引加锁,再在主键索引加锁

慢SQL

查看慢查询日志是否开以及如何开启

  • 查看慢查询日志是否开启:SHOW VARIABLES LIKE '%slow_query_log%';
  • 开启慢查询日志:SET GLOBAL slow_query_log = 1;使用该方法开启MySQL的慢查询日志只对当前数据库生效,如果MySQL重启后会失效。

设置慢SQL的时间阈值

时间阈值是由参数long_query_time控制的,默认情况下long_query_time的值为10秒。

MySQL中查看long_query_time的时间:SHOW VARIABLES LIKE 'long_query_time%';

使用explain分析

  • type:使用什么方式检索
    • const:常数
    • eq_ref:唯一索引
    • ref:普通索引
    • range:范围
    • index:索引树
    • all:全表
  • keys:具体使用哪个索引
  • extra:没有用到索引的原因
    • using where:没有用到索引或者没有用到联合索引的前导列
    • using index:用到了索引覆盖
    • using index condition:用到了索引下推
    • using where;using index:索引在联合索引内,但不是前导列
    • using temporary:用到了临时表,通常是排序或者分组使用
    • using filesort:无法根据索引排序,要在内存排序

OOM

频繁Full GC