How to cleanup ADRCI Homes

ADRCI (ADR Command Interpreter) 是伴随Oracle 11g推出的新工具,由于各种log的位置纷繁复杂,因此在Oracle 11g中,Oracle将数据库、监听、客户端等的Log统一转到了diagnostic_dest初始化参数所指向的目录下的diag目录中,并且提供了ADRCI实用程序来进行高效查询及管理。在这之前我曾经写过两篇跟ADRCI相关的文章。
ADRCI Purge is NOT What You Think It Should Be:ADRCI的Purge命令用于清除日志文件中的内容,但是使用起来并非尽如人意。
Oracle11g for Windows ADRCI Issue:在Windows中使用ADRCI会产生的小问题,当然很久没有用过Windows,不知道这个问题是不是还依然存在。

ADRCI看上去是个很好的东西,但是除了show alert相对简单之外,其它的各种命令和查询条件的指定实际上比较繁琐,因此ADRCI在我周边的使用者寥寥可数,我算是坚持使用的为数不多者。因为使用者不多,所以对于ADRCI中一些极为简单的操作,了解者也比较少。

本文也是如此,如何删除在ADRCI中显示出来的多余的Homes?解决方法简单到令人发指。

问题重现,在命令中show homes显示出6个Home,这通常是由于安装过其它的数据库实例,然后删除的时候遗留下来的Log目录仍然存在。对于完美主义者来说这难以容忍。

[oracle@emnotech rdbms]$ adrci

ADRCI: Release 12.1.0.1.0 - Production on Mon Aug 18 01:34:31 2014

Copyright (c) 1982, 2013, Oracle and/or its affiliates.  All rights reserved.

ADR base = "/u01/app/oracle"
adrci> show home
ADR Homes:
diag/clients/user_oracle/host_266584670_80
diag/tnslsnr/emnotech/listener
diag/rdbms/orcl/orcl
diag/rdbms/slob/SLOB
diag/rdbms/slob/orcl
diag/rdbms/slob/slob

如上所示,ADR的基础目录在/u01/app/oracle,而各个Home都在其下的diag目录中,因此我们直接ls看一下目录结构。

[oracle@emnotech rdbms]$ pwd
/u01/app/oracle/diag/rdbms
[oracle@emnotech rdbms]$ ls -l
total 8
drwxr-x---. 3 oracle oinstall 4096 Jun  3 14:20 orcl
drwxr-xr-x. 5 oracle oinstall 4096 Aug  1 00:36 slob
[oracle@emnotech rdbms]$ ls -l slob
total 12
-rw-r-----.  1 oracle oinstall    0 Jun  5 03:16 i_1.mif
drwxr-xr-x. 16 oracle oinstall 4096 Jun  5 03:16 orcl
drwxr-xr-x. 16 oracle oinstall 4096 Jun  5 03:35 slob
drwxr-xr-x. 16 oracle oinstall 4096 Aug  1 00:36 SLOB

可以看到目录结构与ADRCI命令行中显示的完全一样,所以,解决方法就是直接rm掉不需要的目录。

[oracle@emnotech rdbms]$ rm -rf slob
[oracle@emnotech rdbms]$ ls -l
total 4
drwxr-x---. 3 oracle oinstall 4096 Jun  3 14:20 orcl

友情提示:一定要屡次确认才可以执行rm -rf这样危险的命令,每次对这个命令敲回车我都心惊胆战、心存敬畏。

[oracle@emnotech rdbms]$ adrci

ADRCI: Release 12.1.0.1.0 - Production on Mon Aug 18 01:35:23 2014

Copyright (c) 1982, 2013, Oracle and/or its affiliates.  All rights reserved.

ADR base = "/u01/app/oracle"
adrci> show home
ADR Homes:
diag/clients/user_oracle/host_266584670_80
diag/tnslsnr/emnotech/listener
diag/rdbms/orcl/orcl
adrci>

再次进入ADRCI中查看Homes,世界清静了。

ADRCI Purge is NOT What You Think It Should Be

ADRCI是在Oracle11g以后提供的实用程序,用来更加灵活的检查和分析各个ORACLE_HOME的告警文件,跟踪文件。

根据文档和帮助,ADRCI是具有purge功能的。

adrci> help purge

  Usage: PURGE [[-i  |  ] |
               [-age  [-type ALERT|INCIDENT|TRACE|CDUMP|HM|UTSCDMP]]]:

  Purpose: Purge the diagnostic data in the current ADR home. If no
           option is specified, the default purging policy will be used.

  Options:
    [-i id1 | id1 id2]: Users can input a single incident ID, or a
    range of incidents to purge.

    [-age ]: Users can specify the purging policy either to all
    the diagnostic data or the specified type. The data older than 
    ago will be purged

    [-type ALERT|INCIDENT|TRACE|CDUMP|HM|UTSCDMP]: Users can specify what type of
    data to be purged.

  Examples:
    purge
    purge -i 123 456
    purge -age 60 -type incident

仅仅看这个帮助,我们认为的ADRCI Purge功能是怎样的呢?比如我们执行了下面这个命令,那么Oracle应该将我们的告警日志中在距现在这个时刻1440分钟(也就是1天)以前的所有日志内容删除,是这样吧?可是确实是这样吗?

adrci> PURGE -age 1440 -type ALERT

我们测试一下。

adrci> show home
ADR Homes: 
diag/rdbms/orcl/orcl
diag/tnslsnr/dbserver/listener
adrci> set home diag/rdbms/orcl/orcl
adrci> show alert -tail
2010-05-02 20:04:56.447000 +08:00
Verifying file header compatibility for 11g tablespace encryption..
Verifying 11g file header compatibility for tablespace encryption completed
SMON: enabling tx recovery
Database Characterset is AL32UTF8
No Resource Manager plan active
2010-05-02 20:04:58.182000 +08:00
replication_dependency_tracking turned off (no async multimaster replication found)
2010-05-02 20:04:59.607000 +08:00
Starting background process QMNC
QMNC started with pid=18, OS id=1405 
2010-05-02 20:05:00.653000 +08:00
Completed: ALTER DATABASE OPEN
2010-05-02 20:05:07.033000 +08:00
Starting background process CJQ0
CJQ0 started with pid=19, OS id=1426 
2010-05-02 20:10:00.609000 +08:00
Starting background process SMCO
SMCO started with pid=20, OS id=1587 
2010-05-02 20:11:47.241000 +08:00
Thread 1 advanced to log sequence 16 (LGWR switch)
  Current log# 1 seq# 16 mem# 0: /app/oracle/oradata/orcl/redo01.log

现在告警日志中存在的某两次记录时间是2010-05-02 20:04:56和2010-05-02 20:11:47。我们准备删除掉20:04前后的告警信息,保留20:11的。

[oracle@dbserver alert]$ date
Sun May  2 20:14:20 CST 2010
[oracle@dbserver alert]$ pwd
/app/oracle/diag/rdbms/orcl/orcl/alert
[oracle@dbserver alert]$ ls -l
total 24
-rw-r----- 1 oracle dba 20925 May  2 20:11 log.xml

当前的时间是2010-05-02 20:14。检查了Oracle11g中告警日志的默认存储位置,最后的一次更新时间是20:11。

[oracle@dbserver alert]$ date
Sun May  2 20:15:51 CST 2010

adrci> PURGE -age 5 -type ALERT
adrci> show alert -tail
2010-05-02 20:04:56.447000 +08:00
Verifying file header compatibility for 11g tablespace encryption..
Verifying 11g file header compatibility for tablespace encryption completed
SMON: enabling tx recovery
Database Characterset is AL32UTF8
No Resource Manager plan active
2010-05-02 20:04:58.182000 +08:00
replication_dependency_tracking turned off (no async multimaster replication found)
2010-05-02 20:04:59.607000 +08:00
Starting background process QMNC
QMNC started with pid=18, OS id=1405 
2010-05-02 20:05:00.653000 +08:00
Completed: ALTER DATABASE OPEN
2010-05-02 20:05:07.033000 +08:00
Starting background process CJQ0
CJQ0 started with pid=19, OS id=1426 
2010-05-02 20:10:00.609000 +08:00
Starting background process SMCO
SMCO started with pid=20, OS id=1587 
2010-05-02 20:11:47.241000 +08:00
Thread 1 advanced to log sequence 16 (LGWR switch)
  Current log# 1 seq# 16 mem# 0: /app/oracle/oradata/orcl/redo01.log

[oracle@dbserver alert]$ ls -l
total 24
-rw-r----- 1 oracle dba 20925 May  2 20:11 log.xml

我们执行的命令成功了,但是很明显我们希望的目的没有达到,实际上,就好似没有执行这条命令一样,我们想要删除5分钟以前的内容,执行purge命令的时刻是20:15,那么理应在20:10之前的告警日志内容都被删除掉,但是实际上告警日志中20:04的内容依然还在,并且我们也可以看出log.xml文件的最后更新时间仍然是20:11。

那么purge命令到底有没有效果呢?

[oracle@dbserver alert]$ date
Sun May  2 20:28:34 CST 2010

adrci> PURGE -age 5 -type ALERT
adrci> show alert -tail
adrci> 

[oracle@dbserver alert]$ ls -l
total 0

在20:28的时候我们再次执行了purge命令,仍然是尝试删除5分钟以前的内容,这次的结果是所有的告警日志内容都被清空了,告警日志文件log.xml也被删除了。这条命令实际上有效果的,但是为什么不是我们期望的那样灵敏呢?为什么第一次没有成功,而第二次却成功了呢?

原因在于,ADRCI Purge命令的操作单元是文件而不是文件内容,只有整个文件的最后更新时间在我们指定的purge命令条件之前,该文件才会被删除,也就是说,要不整个文件都删除,要不一点儿也不删除。对于我们后一次执行的命令,因为文件的最后更新时间是20:11,这个时间点在我们执行purge命令时间点的5分钟以前,因此整个告警日志都被删除。而对于我们第一次执行的命令,因为告警日志中不但包含了执行purge命令时间点5分钟之前的内容,还包括了5分钟之前到执行purge命令时间点之间的内容(20:11的内容位于20:10和20:15之间),因此文件无法被删除。

无论是purge的什么TYPE,或者说purge -i 命令也同样是这样,对于INCIDENT来说,每个Incident ID在INCIDENT目录中都是一个子目录,因此很容易做到整个子目录的删除。

不得不说这样的purge命令并不是我们期望的,我也希望看到在今后的版本升级中ADRCI Purge可以变得如我们一开始期望的那样,直接删除符合条件的文件内容,而不是现在这样删除文件。

我们可以预见到对于特别繁忙的系统,假设每分钟都有告警日志内容生成,那么我们始终不可能执行成功purge,我们只能使用purge -age 0 -type ALERT这样的命令来清除所有的log内容。那么现在这样的purge命令我们该如何精确使用呢?

实际上仍然需要另外的客户化脚本,比如在crontab中定义每天晚上的某个时刻将现在的log.xml文件更名为log_`date`.xml,然后统一使用purge命令删除符合条件的告警日志文件备份。特别需要注意的是,更名规则要符合purge命令的检查规范,purge命令只会对相应目录中以log开头以xml结尾的文件进行检查。

PS:purge命令只会清除xml文件,对于trace目录中的和Oracle11g之前版本兼容的alert_.log文件并不会有任何改动。

[oracle@dbserver trace]$ pwd
/app/oracle/diag/rdbms/orcl/orcl/trace
[oracle@dbserver trace]$ ls -l alert*
-rw-r----- 1 oracle dba 41444 May  2 20:20 alert_orcl.log