【新书连载】应用无法连接数据库问题分析

编辑说明:《Oracle性能优化与诊断案例精选》出版以来,收到很多读者的来信和评论,我们会通过连载的形式将书中内容公布出来,希望书中内容能够帮助到更多的读者朋友们。

前不久某运营商客户反映某套业务系统在2016年8月4日凌晨出现过无法访问数据库的情况。当接到客户请求之后我才通过VPN登录进行日志分析。

首先我分析数据库告警日志发现,8月4日凌晨54分开始出现unable to spawn jobq slave process相关错误,如下所示。

从上述告警日志来看,没有明显的ORA相关错误。但是我们细心一点就会发现上述日志中存在一些告警信息,比如kkjcrelp:unableto spawn jobq slave process,该告警也值得我们关注。那么这个告警信息的产生一般有哪些原因呢?

根据kkjcrelp:unableto spawn jobq slave process错误来看,一般有以下几种原因。

(1)数据库进程参数processes参数设置偏小。

(2)job 参数job_queue_processes设置过小。

(3)系统资源(CPU/IO/Memory)不足,例如内存不足,导致新产生的进程无法获取资源。

根据经验我们知道,这极有可能是资源的问题。因为如果是数据库实例processes参数设置偏小,那么alert log通常会伴随 ORA-00200 类似的错误,然而我们却并没有发现。因此我们可以很容易的排除第一种可能性。

至于第2种和第3种可能原因,这里我们暂时还无法排除,还需要进一步分析相关日志才能下结论。

既然是应用程序无法访问,那么数据库监听日志应该会有一些相关记录。我继续检查数据库监听日志发现,4日凌晨确实出现了大量的TNS相关错误,如下所示。

上面这部分内容,我相信大家并不陌生,这是非常常见的一些错误。我相信很多人第一感觉是搜索Oracle MOS,确认TNS-12518 是什么意思,什么原因。想必大家应该会看到这样的文章,ORA-12518 / TNS-12518 Troubleshooting (ID 556428.1)。

该文档描述的解决方案有很多种,这里我大致描述一下,有如下几种。

  • 操作系统时钟问题,建议设置如下参数。

stener.ora: INBOUND_CONNECT_TIMEOUT_listenername SQLnet.ora: SQLNET.INBOUND_CONNECT_TIMEOUT。

  • 操作系统可用内存不足,建议增加内存。
  • 数据库参数processes设置过小,建议调大一些。启用大内存支持,突破内核的单进程只能消耗1GB内存的限制,这实际上通常是指的windows环境。
  • PGA内存不足,而SGA设置过大,导致进程内存不足。建议缩小SGA,给PGA预留更多内存。
  • 配置MTS共享模式。如果监听报错TNS-12518,并进程crash,那么很可能是命中一些因为系统压力过大或者内存溢出等相关oracleBug,例如6139856。

实际上当我们遇到上述类似错误时,不应该直接往下判断。首先在分析这个问题时,我们要确认一点客户所说是否是真实的。也就是说这个问题之前是否出现过,还是仅仅是8月4日凌晨出现过1次。带着这样的疑问,我继续检查分析监听日志,发现实际上8月3日也出现了无法连接数据库的情况。

对于Oracle 的错误分析,我给大家的建议都是应该从下往上看,比如下面所列的错误。

TNS-12518: TNS:listener could not hand off clientconnection TNS-12547: TNS:lost contact TNS-12560: TNS:protocoladapter error TNS-00517: Lost contact SolarisError: 32: Broken pipe

Oracle 监听日志在这里其实抛出了一连串的告警信息,我们需要有所判断,确认其中的哪行信息是关键信息,是产生问题的根源。很明显最后一行的Solaris Error:32:Broken pipe 是此问题的关键所在。针对Solaris error:32 broken pipe错误,这里我不自行进行解释,我选择引用Oracle官方的解释。

The error 32 indicates the communication has been broken while the listener is trying tohand off the client connection to the server process or dispatcher process.

这里我简单解释一下上述文档内容的描述,简单地讲就是:Oracle 监听程序尝试去处理客户端到服务器端进程或者调度器(dispatcherprocesses)进程之前的连接时,将客户端进程通信强行中断了

那么监听程序为什么要终止连接呢?文档解释说有如下几种可能性原因。

1. One of reason would beprocesses parameter being low, and can be verified by the v$resource_limitview. 2. In Shared Server mode,check the 'lsnrctl services' output and see if the dispatcher has refused anyconnections, if so, then consider increasing the number of dispatchers. 3. Check the alert log forany possible errors. 4. Memory resource is alsoanother cause for this issue. Check the swap, memory usage of the OS. 5. IfRAC/SCAN or listener is running in separate home, check the following note。

从Oracle 文档描述来看,产生该问题原因主要有如下几种。

(1)processes参数设置过小。

(2)共享服务器模式下,dispatcher不足。

(3)内存资源不足。

由于客户这里实际上是Oracle10.2.0.4 环境,因此就不需要考虑上述第5条描述了。

从上述问题描述的内容来看,与我们之前讲述TNS-12518 错误几种可能性的原因有些类似。那么我们如何去定位这个问题呢?针对类似的问题,我通常的建议是使用最简单的方法:排除法

首先我们来从数据库层面判断是否可以直接排除第1种可能性原因。我分析了数据库在8月4日凌晨1-2点的AWR数据库,发现数据库进程并没有达到processes参数设置限制,如图13-1所示。

所以可以排除第1种可能性原因。

同时由于数据库是专用模式,因此也可以排除第2种可能性原因。

因此,这里似乎可以大致断定导致此次问题的原因是第3种可能性了,即系统资源使用方面。

我们知道操作系统资源主要分为CPU/IO以及内存资源,接下来从数据库监控角度来判断一下数据库资源在故障期间内的使用情况如何。通过器监控发现,CPU资源消耗正常,swap内存消耗存在一定的波动,但是整体来看也是正常的,如图所示。

基于前面的分析不难看出,系统资源在使用上没有任何问题,没有出现资源过度消耗或资源不足的情况。到这里整个问题的分析似乎陷入了僵局。

Oracle数据库是基于操作系统,因此实际上,当数据库出现异常之后,我们在进行问题分析时,首先应该确认操作系统本身是否正常,比如内核参数设置是否正确等。因此自然而然应该进一步检查数据库服务器操作系统日志是否存在相关蛛丝马迹。

正如心中所想,再检查Solaris操作系统的日志发现,确实存在相关错误。

从上述日志来看,确实存在processes超过限制的情况。同时还能发现有监控用户由于缺乏权限,仍然在不断尝试登陆数据库,这也是一个安全隐患。

针对操作系统日志中的Max number ofDBMS processes execeeded 错误信息,Oracle 官方文档有如下类似解释。

There can be severalcontributors to this failure. Solariskernel may have resource (memory/cpu) shortage, performance problem or thedatabase itself could be having some issues for example:

detected errorDBMS_ERROR: 20 DEFAULT Action=NONE : Max. number of DBMS processes exceeded

说明:参考文档Solaris Cluster 3.x HA-Oracle FaultMonitor Dumps Core With "Aborting fault monitor child process" or"probe response time exceeded timeout" (ID 1381317.1)

根据OracleSolaris的文档解释来看,上述错误ERROR 20表示 Solaris 操作系统本身内核资源使用可能存在异常,或者存在性能问题,或者数据库本身可能存在某些问题。这个分析与我们前面的种种分析似乎比较接近。

这里我需要说明的是,我期间分析了故障前后的AWR和ASH 相关数据,没有发现明显异常,因此可以断定数据库本身是正常的

分析到这个层面,我相信大家心中已经有了答案。有没有可能是操作系统本身有问题呢?这里需要注意的是,操作系统本身有问题,并不代表是指的操作系统资源使用有问题,也有可能是Solaris 相关内核参数设置问题。实际上我们通过前面的操作系统监控信息就可以排除系统资源消耗异常的可能性。

所以这里我们很有必要对Solaris系统本身的相关内核参数进行全面检查一次,通过检查发现确实存在参数设置不合理的情况,如下所示。

---操作系统内核参数

root@nxfwktdb # cat /etc/system|grep 'sys' set semsys:seminfo_semmni=100 set semsys:seminfo_semmns=2048 set semsys:seminfo_semmsl=256 set semsys:seminfo_semvmx=32767 set shmsys:shminfo_shmmax=17179869184 set shmsys:shminfo_shmmin=1 set shmsys:shminfo_shmmni=100 set shmsys:shminfo_shmseg=10 root@nxfwktdb # cat /etc/project system:0:::: user.root:1:::: noproject:2:::: default:3:::: group.staff:10::::

---数据库会话总数

SQL> select count(1) from v$session; COUNT(1) ---------- 1866

对于上述的内核参数,这里我不做过多解释,大家可以参考Oracle官方安装文档,里面有详细的描述。从Soalris 10开始,已经废弃了如下几个参数:

semsys:seminfo_semmns——操作系统信号灯最大个数;

shmsys:shminfo_shmmin——共享内存段最小值;

semsys:seminfo_semvmx——操作系统信号灯的最大值。

同时,从Solaris 10开始,已经不再建议通过修改/etc/system的方式来调整内核参数了。建议通过project的方式来进行控制,而客户这里没有为Oracle用户单独创建project,而使用了默认的default project,如下:

root@nxfwktdb # id -p oracle uid=101(oracle) gid=100(dba) projid=3(default)

那么我们来进一步检查default project设置是否恰当。其中Solaris 10版本中使用process.max-sem-nsems来替代 semsys:seminfo_semmsl 参数的控制,该参数表示一个信号组中信号灯等最大数量,由于Oracle用户默认使用了default project,因此这里我们来检查default project的设置情况,如下所示。

我们可以看到default project中定义了project.max-sem-ids它表示系统中信号组的最大值,即128,表示目前该系统最大default project中所定义的用户创建的最大信号组之和不能超过128。同时/etc/system中的参数semsys:seminfo_semmsl 为256,表示该default project 的每一个信号组最大只能创建256个信号灯。可以通过ipcs 命令直接查看这一点。

上述查询结果的NSEMS 列即表示每个信号组中最大的信号灯数量。同时从NATTCH的值可以看出,目前当前Oracle用户已经创建了1 870个进程。实际上seminfo_semmsl参数的设置应该是大于processes参数设置的。目前数据库processes参数设置为2048,且数据库进程已经超过1850,因此建议将该参数调整的更大一些。

从前面的数据来看,目前default project中所有用户能够消耗的最大信号灯约等于128×256=32768。尽管这个数值看上去已经够大,其实不然。在操作系统命令来看,一个进程和信号灯等对应关系通常是一对多。而且从查询结果来看Oracle实际上只分配了9个信号组,每组最大的信号灯数量是256。如果根据这个计算也就是9×256=2304。而目前数据库实例的进程数量已经接近2000。

因此最后我们建议将seminfo_semmsl参数调整的更大一些,建议设置为512以上。

至此,本案例分析完毕。

对于DBA来说,具备全局的技术观非常重要。因为我们遇到的问题通常不是单一原因导致的,只有掌握多方面的知识,才能在遇到故障时思维不受限,且能更好地利用各类日志信息进行分析排查。

原文发布于微信公众号 - 数据和云(OraNews)

原文发表时间:2017-03-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏battcn

没有Eureka,但多了Nacos

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。

1082
来自专栏IT大咖说

饿了么API Everything解决了前后端开发之间的所有问题?

简单来说就是后端服务通过API的形式对外暴露,作为前端访问后端的中间层。API Everything会将SOA服务接口适配给外部各端进行访问。

1582
来自专栏全华班

一款免费、开源,使用sprinbboot快速开发管理系统

BootDo是在SpringBoot基础上搭建的一个Java基础开发平台,MyBatis为数据访问层,ApacheShiro为权限授权层,Ehcahe对常用数据...

9481
来自专栏喵了个咪的博客空间

phalapi-进阶篇1(Api,Domain,和Model)

#phalapi-进阶篇1(Api,Domain,和Model)# ? ##前言## 先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个...

3627
来自专栏企鹅号快讯

千万千万不要运行的 Linux 命令

来源:Linux 中国 https://linux.cn/article-401-1.html 文中列出的命令绝对不可以运行,即使你觉得很好奇也不行,除非你是在...

3807
来自专栏架构师之路

数据库软件架构设计些什么

缘起:受@萧田国 萧总邀请,上周五晚上在“高效运维1号群”内分享了《58同城数据库软件架构设计与实践》(这个topic今年在数据库大会上分享过),应组织方要求,...

36211
来自专栏大魏分享(微信公众号:david-share)

互联网架构中的9种隔离术以及容器化的实现

9种隔离术 在硬件方案设计的时候,我们常提到过一个概念“故障域”。故障域指的是当一个区域出现故障以后,它的受影响范围。例如在设计双活数据中心的时候,我们要设置故...

5834
来自专栏Java帮帮-微信公众号-技术文章全总结

【大牛经验】搜狗商业平台Java技术实践

搜狗商业平台Java技术实践 Java自1995年问世以来,已历经20多年岁月。20年来,IT技术风起云涌,Java始终以其可移植性、跨平台性、生态系统完备性等...

40010
来自专栏phodal

博客系统的架构思考(中)——静态与CQRS

对于复杂的系统来说,上一篇的做法做确实很不错。但是对于一个简单地系统来说,这样做是不是玩过火了?如果我们要设计一个博客系统的话,那么我们是不是可以考虑将Writ...

2169
来自专栏Java技术

数据库分库分表策略的具体实现方案

:http://blog.csdn.net/xlgen157387/article/details/51331244

2334

扫码关注云+社区