Can We Delete $ORCLE_HOME/.patch_storage

问:$ORCLE_HOME/.patch_storage占据了7-8G的空间,能否删除?

答:该目录不能直接删除,但是可以通过opatch命令做一定的清理。

该目录的作用可以参看Metalink Note: 403218.1

该目录中保存着每次Patch涉及到的文件的备份还有local inventory的备份,如果我们要做patch rollback就需要存储在这个目录中的信息,下面几种情况都必须要做Patch Rollback。
1. 某些之前的Patch跟现在需要的Patch冲突,则必须先Rollback之前的Patch。
2. 最新的CPU (Critical Patch Update) Patch总是包含前一版本的Patch内容,因此每次打CPU Patch都会自动做一次前一版本Patch的Rollback。

如何通过opatch命令清理该目录可以参看Metalink Note: 550522.1

在新版的OPatch中,新增了util命令,通过该命令可以清理.patch_storage目录。

具体的命令为:opatch util cleanup

帮助信息:opatch util cleanup -help

$ opatch util cleanup -help
Invoking OPatch 10.2.0.3.4

Oracle Interim Patch Installer version 10.2.0.3.4
Copyright (c) 2007, Oracle Corporation. All rights reserved.

UTIL session

DESCRIPTION
This utility cleans up 'restore.sh,make.txt' files and 'rac,scratch,backup'
directories of the.patch_storage directory of Oracle Home.If -ps option is used,
then, it cleans the above specified areas only for that patch, else for all
patches under ORACLE_HOME/.patch_storage. You will be still able to
rollback patches after this cleanup.

SYNTAX
opatch util cleanup [-invPtrLoc  ]
[-jre  ] [-oh  ]
[-silent] [-force] [-report]
[-ps , this will
be located under ORACLE_HOME/.patch_storage/]

示例:

$ opatch util cleanup
Invoking OPatch 10.2.0.3.4

Oracle Interim Patch Installer version 10.2.0.3.4
Copyright (c) 2007, Oracle Corporation. All rights reserved.

UTIL session

Oracle Home : /home/oracle/10.2.0.3
Central Inventory : /home/oracle/oraInventory
from : /etc/oraInst.loc
OPatch version : 10.2.0.3.4
OUI version : 10.2.0.3.0
OUI location : /home/oracle/10.2.0.3/oui
Log file location : /home/oracle/10.2.0.3/cfgtoollogs/opatch/opatch2008-02-12_10-33-40AM.log

Invoking utility "cleanup"
OPatch will clean up 'restore.sh,make.txt' files and 'rac,scratch,backup' directories.
You will be still able to rollback patches after this cleanup.
Do you want to proceed? [y|n]
y
User Responded with: Y
Size of directory "/home/oracle/10.2.0.3/.patch_storage" before cleanup is 438057972 bytes.
Size of directory "/home/oracle/10.2.0.3/.patch_storage" after cleanup is 198415929 bytes.

UtilSession: Backup area for restore has been cleaned up. For a complete list of files/directories
deleted, Please refer log file.

OPatch succeeded. 
$ 

如果在执行了上述命令之后,还觉得.patch_storage占用了过大的空间,那么可以更进一步的做手工清理。
执行’opatch lsinventory’命令,查看输出,然后手动删除.patch_storage目录中所有不在输出列表中的子目录。

Something about Oracle Load Balance

虽然在Oracle的立场上,总是建议客户能够更好地规划自己的应用,在有其它负载平衡方法的时候,尽量不要依赖于Oracle的Load Balance方法,但是往往在给客户配置完Oracle RAC数据库以后,客户都会要求要测试负载平衡(Load Balance)和TAF(Transparent Application Failover),并且将这两个测试作为RAC是否安装成功的标准。

这是一件很无奈的事情,像把旁枝末节看作了主要功能,甚至有些买椟还珠的感觉,但是毕竟这是客户,更了解Oracle Load Balance(后文用LB表示),才可以更好满足客户需求。

本文不牵涉TAF(可以参看老熊关于TAF的系列文章PartIPartIIPartIII),如何在Oracle10g之后版本中在服务器端service层面设置TAF,可以参看Metalink Note: 404644.1

对于LB,在Oracle10g之前有Client端和Server端两种,在Oracle10g之后又推出了Server端Service层面的LB配置,本文也不涉及Service层面的LB。

在Oracle9i,10g,11g版本中都适用的LB配置分为以下两种。

(1) Client Side Connect Time Load Balance
(2) Server Side Listener Connection Load Balance (此处的Listener用以跟10g之后的Server Side Service Load Balance区分开)

1. Client Side Connect Time Load Balance
既然是Client端的LB,那么也就是不需要在数据库服务器端配置任何参数,完全由客户端机器上的tnsnames.ora文件中对于TNS的配置来决定,实际上也就是LOAD_BALANCE参数。

看一个例子,下面这样的TNS配置就是启用了客户端的LB。

CLIENT_LOADBALANCE =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = node1-vip)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = node2-vip)(PORT = 1521))
      (LOAD_BALANCE = yes)
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = rac_lb)
    )
  )

(LOAD_BALANCE = yes)指示SQLNet随机选择ADDRESS_LIST列表中的任意一个监听,将客户端请求发送到此监听上,通过这种方法来实现负载平衡。如果(LOAD_BALANCE = no)那么将会按照ADDRESS_LIST列表中的顺序选择监听,只要这个监听能够正常连接那么就使用该监听。

因此在某些负载平衡的解决方案中会使用(LOAD_BALANCE = no)但是在多个客户端或者应用服务器端配置顺序不同的ADDRESS_LIST,以此来实现人为的负载平衡。

如果在TNS配置时使用的是ADDRESS_LIST语法,那么必须显示设置LOAD_BALANCE = yes,默认值LOAD_BALANCE = no。

2. Server Side Listener Connection Load Balance
要实现server side load balance要求监听能够知道在整个RAC环境中的各节点负载情况,节点负载情况是由PMON进程来定期更新的,而要让PMON进程能够通知其它节点自己节点的负载情况则需要设置数据库初始化参数REMOTE_LISTENER。

在RAC数据库服务器端的每个节点上的tnsnames.ora文件中设置如下的TNS名称。

LISTENERS_RAC =
(DESCRIPTION =  
 (ADDRESS_LIST =   
  (ADDRESS = (PROTOCOL = TCP)(HOST=node1-vip)(PORT = 1521))   
  (ADDRESS = (PROTOCOL = TCP)(HOST=node2-vip)(PORT = 1521))   
 )  
) 

然后设置REMOTE_LISTENER参数值为LISTENERS_RAC。

sql> alter system set REMOTE_LISTENER='LISTENERS_RAC' scope=both;

当某个实例的监听收到客户端连接请求,将会统筹考虑RAC环境中各个节点的负载情况,然后将该连接传递到具有最小负载的节点的最小负载实例上。

在10gR2版本之后,节点和实例的负载计算通过lbscore来完成,而lbscore则由两个动态值决定:”goodness” 和 “delta”,这两个值均由PMON来定期更新,计算公式如下:
Lbscore = Goodness (Received from PMON update)
Delta = New Delta (Received from PMON update)
在PMON定期更新的间隔,如果有新连接进入,那么lbscore的计算公式是:
Lbscore = Lbscore(previous) + Listener Delta

可以通过添加监听的trace(TRACE_LEVEL_LISTENER = 16)来获取lbscore的产生情况,更详细的文档请参看Metalink Note: 263599.1。

关于Failover,多说两句,其实Failover也有两种。
一种是Client-side Failover。细分为Client-side Connect Time Failover,由客户端TNS配置的(failover=on)参数控制,或者Client-side TAF,由客户端TNS配置中的failover_mode参数控制。
另外一种是Server-side Failover。通常跟Server-side Service LB同时配置,通过modify service来完成。

Understand XID in Database View and Trace File

我们知道Transaction ID(XID)的组成是:Undo segment No. + Slot No. + Sequence No.

但是在数据字典中查询出来的XID和跟踪文件中的XID表现形式却有所不同,跟踪文件中的更加直观,而数据字典中的则需要做简单转换。

比如有一个事务,在数据字典中对应的Undo Block是:

SQL> select UBAFIL,UBABLK from v$transaction;
 
    UBAFIL     UBABLK
---------- ----------
         3       1854

获取block dump跟踪文件。

SQL> alter system dump datafile 3 block 1854; 
 
System altered 

SQL> @gettrace;
 
TRACEFILE
--------------------------------------------------------------------------------
d:\oracle\diag\rdbms\orcl11g\orcl11g\trace\orcl11g_ora_1380.trc

检查orcl11g_ora_1380.trc中的相应内容可以看到xid的格式是:xid: 0x0006.002.000004d1,为16进制。

其中0006 = 10进制的6
002 = 10进制的2
000004d1 = 10进制的1233

因此我们可以知道对于这个事务,Undo segment No是6,Slot No是2,Sequence No是1233。

从v$transaction视图中也可以验证。

SQL> select XIDUSN,XIDSLOT,XIDSQN from v$transaction;
 
    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         6          2       1233

但是查询v$transaction视图中的XID字段,却得到看上去不太一样的数值。

SQL> select XIDUSN,XIDSLOT,XIDSQN,XID from v$transaction;
 
    XIDUSN    XIDSLOT     XIDSQN XID
---------- ---------- ---------- ----------------
         6          2       1233 06000200D1040000

在这里我们需要做一下转换。
1. 06000200D1040000 = 0600.0200.D1040000
2. 再做高低位互换,0600 => 0006,0200 => 0002,D1040000 => 000004D1
3. 获得XID = 0006.0002.000004D1,这时跟block dump中记录的xid就完全一样了。

via Comment@babyblue
通过SQL来获取就是:

select to_number(substr(xid, 3, 2) || substr(xid, 1, 2), 'xxxxxxxxxxxx') xidusn,
       to_number(substr(xid, 7, 2) || substr(xid, 5, 2), 'xxxxxxxxxxxx') xidslot,
       to_number(substr(xid, 15, 2) || substr(xid, 13, 2) ||
                 substr(xid, 11, 2) || substr(xid, 9, 2),
                 'xxxxxxxxxxxx') xidsqn
  from (select '06000200D1040000' xid from dual);