前两天YJ部门有一个使用occi的应用,启动时出现报错,应用日志记录的内容是Occipool error,没有任何其他信息了,后来同事向应用中加了一些日志语句,重编译运行才发现报的是ORA-00020错误,数据库process连接进程达到了上限,通过参数修改,解决了这个问题。这里我要说的是在排查过程中看到的另外一个报错。
为了更好地说明问题,我会结合实验一并叙述。
问题现象:
首先,查找sqlnet.log所在路径:
find . -name sqlnet.log
./home/oracle/oradiag_oracle/diag/clients/user_oracle/host_2027447528_80/trace/sqlnet.log
在一个session中执行一个错误的sqlplus:
sqlplus a/a
SQL*Plus: Release 11.2.0.4.0 Production on Sat Sep 24 23:04:21 2016
Copyright (c) 1982, 2013, Oracle. All rights reserved.
ERROR:
ORA-01017: invalid username/password; logon denied
再查看sqlnet.log日志:
tail -0f sqlnet.log
Sat Sep 24 21:08:07 2016
Directory does not exist for read/write [/u01/app/oracle/product/11.2.0.4/log] [/u01/app/oracle/product/11.2.0.4/log/diag/clients]
提示找不到用于写入和读取的目录:
/u01/app/oracle/product/11.2.0.4/log
/u01/app/oracle/product/11.2.0.4/log/diag/clients
这是什么意思?为啥提示这么个错误?
问题排查:
1.首先,涉及的就是11g的一个新功能,ADR,全称是Automatic Diagnostic Repository,即将所有trace文件、core文件、alert文件等做了统一管理,存放于一个目录结构中,对于不同的实例、产品,例如数据库、ASM、CRS,都会在ADR中有自己的目录结构管理这些文件,之所以要统一目录,目的就是为了让客户还有Oracle支持能方便地关联和分析不同实例的诊断数据。以前的版本,若需要这些文件,则在不同的目录中查找。
如下文章对ADR做了非常详细的说明:
Understanding Automatic Diagnostic Repository. (文档 ID 422893.1),eygle的《深入解析Oracle:数据库的初始化》对ADR也有过非常详细的介绍,另外,我之前写过一篇文章:http://blog.csdn.net/bisal/article/details/50284991
ADR的根存储位置是由diagnostic_dest参数来决定,即ADR BASE,ADR目录结构是固定的,ADR的下一级目录名称是diag,ADR BASE下可以有各自的ADR HOME,格式如下:
diag/<product_type>/<prod_id>/<instance_id>
对于diagnostic_dest的默认值:
如果ORACLE_BASE环境变量已经设置,则diagnostic_dest参数值就是ORACLE_BASE。
如果ORACLE_BASE环境变量未设置,则diagnostic_dest参数值设置为ORACLE_HOME/log。
通过v$diag_info视图可以查询ADR的存储路径。
同时,ADR还提供了一个命令行工具adrci,但实际上没必要登录adrci操作,因为ADR中的数据仅用于诊断问题,并没有出于安全考虑做一些特殊处理,唯一可以有的就是ADR目录要遵守操作系统的权限要求。
2.除了数据库可以使用ADR目录,客户端,同样也可以使用,并且其默认的ADR目录是ORACLE_HOME/log,若此目录不存在,则ADR目录会创建在HOME中,例如:
$HOME/oradiag_<owning user>/diag/clients/user_<owning user>/host_*
此时可从以下目录查看sqlnet.log或log.xml文件:
$HOME/oradiag_<owning user>/diag/clients/user_<owning user>/host_*/trace/sqlnet.log
$HOME/oradiag_<owning user>/diag/clients/user_<owning user>/host_*/alert/log.xml
我们看下实际的情况,
sqlplus a/a
tail -0f sqlnet.log
Sun Sep 25 20:31:52 2016
Directory does not exist for read/write [/u01/app/oracle/product/11.2.0.4/log] []
/u01/app/oracle/product/11.2.0.4/log就是ORACLE_HOME/log路径,接下来创建这个路径,再次执行时HOME下sqlnet.log不会写入任何信息。之所以之前sqlnet.log有内容,是因为缺少需要的目录文件夹。当然这还有一个前提,就是未开启sqlnet客户端trace,此时不会有任何信息写入ADR目录。
使用sqlnet.ora还可以指定ADR路径,如果需要验证ADR目录正确与否,是否还会写入HOME中,只需要设置sqlnet客户端trace,
vi $ORACLE_HOME/network/admin/sqlnet.ora
DIAG_ADR_ENABLED=on
ADR_BASE=/u01/app/oracle/log
trace_level_client=16
查看:
cd /u01/app/oracle/log/oradiag_oracle/diag/clients/user_oracle/host_2027447528_80/trace
ls -rlht
-rw-rw----. 1 oracle oracle 156 Sep 25 21:51 sqlnet.log
-rw-rw----. 1 oracle oracle 45K Sep 25 21:51 ora_3303_140094482417408.trm
-rw-rw----. 1 oracle oracle 228K Sep 25 21:51 ora_3303_140094482417408.trc
查看sqlnet.log,
Sun Sep 25 21:51:47 2016
Create Relation ADR_CONTROL
Create Relation ADR_INVALIDATION
Create Relation INC_METER_IMPT_DEF
Create Relation INC_METER_PK_IMPTS
初始化创建一些ADR信息。trc文件则记录了本次sqlplus的trace信息。另外,log.xml中记录了,
cd /u01/app/oracle/log/oradiag_oracle/diag/clients/user_oracle/host_2027447528_80/alert
vi log.xml
<msg time='2016-09-25T21:51:47.971+08:00' org_id='oracle' comp_id='clients'
msg_id='dbgrmmdcrf_create_relation_full:1945:1503427940' type='NOTIFICATION' group='create'
level='16' host_id='bisal' host_addr='::1'>
<txt>Create Relation INC_METER_IMPT_DEF
</txt>
</msg>
<msg time='2016-09-25T21:51:47.987+08:00' org_id='oracle' comp_id='clients'
msg_id='dbgrmmdcrf_create_relation_full:1945:1503427940' type='NOTIFICATION' group='create'
level='16' host_id='enmoedu' host_addr='::1'>
<txt>Create Relation INC_METER_PK_IMPTS
</txt>
</msg>
若不需要产生trace,可以注释sqlnet.ora中trace_level_client=16这行即可。
总结:
1.11g中不仅是数据库,客户端是同样可以使用ADR,数据库ADR默认路径由diagnostic_dest参数决定,默认值是ORACLE_BASE,客户端ADR默认路径是ORACLE_HOME/log,如果此路径不存在,则会将ADR创建于HOME中。
2.如果客户端,ORACLE_HOME/log未创建,则HOME中的sqlnet.log会记录缺少目录,若不想出现这种错误,有两种做法:
(1) 手工创建日志中记录缺少的目录。
(2) ORACLE_HOME/network/admin/sqlnet.ora中指定ADR路径:
DIAG_ADR_ENABLED=on
ADR_BASE=/u01/app/oracle/log
3.如果需要打开sqlnet客户端trace,可以在ORACLE_HOME/network/admin/sqlnet.ora增加:
trace_level_client=16
对于客户端sqlnet.ora的变动,仅需要重启应用,对于服务端sqlnet.ora的变动,则需要重启监听。
若是使用了EM的agent,需要重启agent,若仅是sqlplus,则无需任何操作,立即生效。