上周四公司发版,又是搞到晚上12点以后,以为万事大吉,结果第二天生产验证发现接口响应比之前慢,然后开始排查问题。
由于公司电脑不能拍照截图,只能回忆下当时日志报错信息。主要是JDBC连接超时。刚开始以为是连接池的问题,结果查询发现生产库的最大连接数是10000,以及当前的的连接数为240。很明显,不是连接池满的原因。
--查询数据库允许的最大连接数
select value from v$parameter t where t.name = 'processes';
--查询数据库并发连接数
select count(1) from v$session t where t.status='ACTIVE';
然后,登录服务器端,用top命令查看,结果如下,直接锁定PID为5196这一行。CPU占了98.2%。

如何根据PID定位是哪个SQL呢,需要结合Oracle自带的数据字典查看。
--根据系统进程PID查询对应的物理地址
select v.addr,
v.*
from v$process v
where v.spid = '5196';
查询结果如下:

--根据物理地址查找对应的SQL_ID
select t.sql_id,
t.*
from v$session t
where t.paddr= '000000007F48E090';
查询结果如下:

--根据SQL_ID来查找对应的SQL语句
select sql_text
from v$sql
where sql_id = '980b47damaakk';
--将上面三条sql关联起来,合并成一条sql:
select s.sql_text
from v$sql s,
v$session t,
v$process v
where s.sql_id = t.sql_id
and t.paddr = v.addr
and v.spid = '5196'; --代入 top命令查询到的cup偏高的PID
定位出导致cpu冲高的根因了,原来是下面这条sql,很明显,这条sql 两表关联,但是没有关联条件,导致执行计划走的是笛卡儿积。
select count(1) from test a,test b where 1 = 1;
总结: 针对以上这种原因,上线之前尽量做好SQL审核,如果测试同事有时间,除了做功能测试,最好也做性能测试。除了SQL执行计划走的是笛卡尔积,如果表索引未正确创建,也有可能会导致服务器CPU冲高。




