故障类型
数据库连接模式
现象错误号
第一 在后台服务器和数据库很空闲的情况下,前台业务系统却很卡甚至瘫痪
第二 每次重启数据库的十几分钟之内是很正常,但那之后又很卡
故障描述
某客户数据库7月13日11点左右从原先老服务器切换至新服务器,切换完成之后,数据库版本主机操作系统版本都保持不变。运行20天左右,从8月4日开始,前台操作人员反应业务程序响应出现延迟,此后延迟逐渐增大。8月5日远程经过仔细诊断后发现存在大量磁盘读,采取增大SGA数据库内存的方式来减少磁盘读。但调整之后即第二天8月6日上午应用几乎瘫痪无法操作,后台数据库却很空闲。重启数据库业务程序卡顿消失,但过了十几二十分钟之后现象又产生,排除了网络和业务程序自身的故障后,考虑到事故的紧急性采取重启数据库临时解决问题。8月6日下午到达现场仔细排查之后确认是由于连接方式所导致的故障,调整部分参数之后恢复正常,增大SGA后业务程序响应速度明显加快,部分报表查询甚至提升了十几倍。
故障原因分析
前端业务程序正是采取了共享的连接模式(多个客户端进程对应一个服务器进程),由于数据库服务进程有限,导致业务程序发出的请求没有及时被后台服务进程处理。
进一步查看数据库共享模式下相关参数配置:
数据库配置了初始化5个共享服务进程(最大15个)和15个调度进程,我们通过DBA_HIST_RESOURCE_LIMIT来查询相关进程的繁忙程度。
以上的查询结果我们可以看出 max_shared_servers 已经达到阈值
SQL> show parameter shared_server
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
max_shared_servers integer 15
shared_servers integer 5
SQL> show parameter dispatchers
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
dispatchers string (protocol=TCP)(disp=5)
max_dispatchers integer 15
SQL> select to_char(dhs.begin_interval_time,'yyyy-mm-dd hh24:mi:ss') begin_time,
2 to_char(dhs.end_interval_time,'yyyy-mm-dd hh24:mi:ss') end_time,
3 dhs.error_count,
4 dhr.current_utilization,
5 dhr.max_utilization,
6 dhr.initial_allocation,
7 dhr.limit_value
8 from DBA_HIST_SNAPSHOT dhs, dBA_HIST_RESOURCE_LIMIT dhr
9 where dhs.snap_id = dhr.snap_id
10 and dhr.resource_name = 'max_shared_servers'
11 and dhs.begin_interval_time >= sysdate - 3
12 order by dhs.begin_interval_time
13 ;
BEGIN_TIME END_TIME ERROR_COUNT CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_AL LIMIT_VALU
--------------------- ------------------------ ------------------- --------------- ---------- ----------
2015-08-05 00:00:50 2015-08-05 01:00:51 0 5 15 15 15
2015-08-05 01:00:51 2015-08-05 02:00:53 0 5 15 15 15
2015-08-05 12:00:11 2015-08-05 13:00:12 0 5 15 15 15
2015-08-05 13:00:12 2015-08-05 14:00:14 0 5 15 15 15
2015-08-05 14:00:14 2015-08-05 15:00:16 0 5 15 15 15
2015-08-05 15:00:16 2015-08-05 16:00:18 0 5 15 15 15
·········
2015-08-06 15:00:28 2015-08-06 16:00:31 0 10 15 15 15
2015-08-06 16:00:31 2015-08-06 17:00:34 0 5 15 15 15
2015-08-06 17:00:34 2015-08-06 18:00:36 0 15 15 15 15
由于返回结果较多省略部分结果

从以上的查询结果和awr报告中我们可以大致确定是由于共享服务进程无法及时处理请求队列中的用户请求。这也很好解释了每当数据库重启后,少量请求的情况下共享服务进程还是比较及时的处理用户的请求,随着请求数的增多和大事务的处理(比如报表),导致共享服务进程达到阈值,无法及时响应,最终导致前台业务卡死。
故障总结
从本次故障分析来看,随着业务量的增大及高峰期报表的执行,默认共享模式下的服务进程数量无法满足当前的需求,共享模式主要针对高并发小事务的OLTP系统而言,在如今内存充足的情况下推荐采用独占模式的连接方式。主要建议如下:
1. 报表客户端连接方式改为独占模式
2. 调大共享模式服务进程数量(调整 max_shared_servers 和 shared_servers 的值 )
3. 优化部分SQL减少单个服务检查的处理时间
共享模式知识点
下面具体对共享模式的工作原理做简要分析:
共享模式主要分为6个步骤(如图1-1):
1. 用户发起连接请求
2. 监听监测到请求返回调度进程地址,此时用户进程与空闲调度进程直接连接
3. 用户发起操作请求(如dml),调度进程负责把请求放入请求队列中
4. 空闲的共享服务进程从请求队列中接过请求,后台处理
5. 共享服务进程处理完请求,把结果放入相应队列中
6. 对应的调度进程从相应队列中把结果返回给前端用户

图:1-1