最近在多个项目中遇到系统卡顿的问题,总结多次问题处理的结果,做个简单的分享。
问题现象
应用报网络通信异常或连接超时。
处理方法
1、 慢SQL处理
(1) 生产环境,通过
select sf_get_session_sql(sess_id) full_sql,datediff(ss,last_send_time,current_timespamp()) time_used,* from v$sessions where state=’ACTIVE’ order by 2 desc
找出慢SQL并导出到excel中,查看当前SQL计划是否正常,如果不正常针对慢SQL进行优化(注意上班时间禁止操作);如果SQL执行正常,大部分情况是内存中的计划和当前计划不一样,有可能是统计信息不准导致,可以通过inject绑定计划的方式绕过(谨慎收集统计信息,只能在非上班时间做)。
(2) 通过vleng_exec_sqls或者VSQL_HISTORY视图查看。同样先查看当前计划,再查看内存中的计划。
(3) 查看内存中的计划。
A、 通过trace文件查看
–先确认sql对应的执行计划缓存号cache_item
select cache_item,sqlstr,* from vcachepln where sqlstr like '%SQL语句片段%' ;
然后通过trace文件进行分析
--假定cache_item=123456
Alter session set events 'immediate trace name plndump,level 123456';
然后到数据库的trace目录下(一般在../DAMENG/trace下面),具体查看方法这里省略。
如果看到计划和现在不一样,可以清理单条SQL的计划,
--假定需清理的缓存号为123456'
sp_clear_plan_cache('123456');
B、 通过系统包查看
通过系统自带的DBMS_SQLTUNE包查看,使用包内的过程和函数之前,如果还未创建过系统包,请先调用系统过程创建系统包。SP_CREATE_SYSTEM_PACKAGES (1,'DBMS_SQLTUNE');
另外需要ENABLE_MONITOR和MONITOR_SQL_EXEC 均设置为 1。
然后执行SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_EXEC_ID=>123)
其中SQL_EXEC_ID可通过视图VSQLTEXT、VSESSIONS、VSQL_HISTORY、V$LONG_EXEC_SQLS等视图中查询。
2、 连接池配置问题
应用连接池配置的时候,都有初始值、最小值、最大值,现在的业务系统并发越来越大,当初始值太小时,并发上来后就会新建连接,而新建连接耗时比较大,这样就导致部分SQL执行很快,但是通过系统视图监控时发现时耗时较长。特别是读写分离情况下,会执行下面这条SQL:
select distinct mailIni.mal_inst_name, mailIni.mal_INST_HOST, mailIni.mal_INST_PORT, archIni.arch_status from v$arch_status archIni left join (select * from V$DM_MAL_INI) mailIni on archIni.arch_dest = mailIni.mal_inst_name left join V$MAL_LINK_STATUS on CTL_LINK_STATUS = 'CONNECTED' AND DATA_LINK_STATUS = 'CONNECTED' where archIni.arch_type in ('TIMELY', 'REALTIME')
这样在分析问题的时候就会误导我们。这时候需要到dem(尽量每个项目都部署)中查看会话信息,查看是否存在会话增加比较明显,如果会话增加明显,说明就是连接池配置的问题,需要将最小值和初始化设置大一点。
比如这种情况,可以把初始值和最小值都设置为50。
经验分享
1、 分页慢
最近遇到SQL执行很快10ms以内,结果集也就几条,可是加上limit 0,20或者其他分页的时候巨慢,1分钟出不来结果,多方分析后发现是TOP_ORDER_OPT_FLAG=1导致,这个参数是默认参数,大部分都时1,下次遇到类似问题时优先排查这个。Bug系统已提交bug,后面可以参考下修改进去。
2、 Hash导致慢
针对多表关联,当关联列具有很好的过滤性时,尽量走nest loop index join,避免走hash join,因为hash join在并发情况下,资源消耗比较大,加上数据量大,从而导致查询异常慢。
如下面这条SQL:
select t.*, messages_mobile_config.istop from (select test1.*, row_number () over ( partition by typeguid order by sendtime desc) rn from test1 where 1=1 and test1.targetuserid = ? and test1. status !=9) t
left join test2 on t.typeguid = test2 .typeguid and t.targetuserid = test2 .userid where rn = 1
默认走的hash join,导致查询异常慢,通过inject,禁用hash_join后正常。Hint:enable_hash_join(0)。
文章
阅读量
获赞