Install GI and DB PSU 11.2.0.2.5 Failed in VirtualBox

Oracle的Apply Patchset的方法一直是为人诟病的,其实步骤复杂倒也罢了,怕的是Oracle总在不停地修改Apply Patch的方法,Oracle的原意是让Apply Patch的语法越来越简单,但是各种各样的Patch,各种不同的命令,特别是很大的Bundle Patch,如果不仔细阅读Readme,千万不要轻易出手。

这次尝试在自己的VirtualBox虚拟机OEL6中给之前安装的GI(Oracle Restart)+ ASM + Oracle Database安装最新的11.2.0.2.5 PSU,遇到各种问题。

1. Patch解压的目录必须是grid用户和oracle用户拥有写权限的,如果没有写权限,会报错:

Opatch version check failed for oracle home  /u01/app/oracle/product/11.2.0/dbhome_1
Opatch version  check failed
update the opatch version for the failed homes and retry

安装需求是使用root用户来安装(这是我第一次看到在安装PSU的时候要求使用root用户),而我的虚拟机中由于没有足够的磁盘空间,所以将Mac中的下载目录作为Shared Folder映射到虚拟机中,因此改目录的属主是root,用户组是vboxsf,而且并不允许使用chmod直接修改。因此出现了权限问题。我的解决方法是将grid用户和oracle用户都加入vboxsf组中。

建议:在真实环境中,Patch解压目录应该属于dba用户组。

2. 我的Patch是解压在/media/sf_PSU目录下,解压以后生成了p13343447_112020_Linux-x86-64目录,其下有两个目录分别是13343424(这是DB PSU)和13343447(这是GI PSU),整个目录结构如下所示:

 |-media
 |--sf_PSU
 |---p13343447_112020_Linux-x86-64
 |-----13343424
 |-----13343447

按照Readme文档中描述的,opatch的命令应该写为:

opatch auto 

此处的UNZIPPED_PATCH_LOCATION按照文档描述应该就是/media/sf_PSU目录,因为这是解压目录,但是实际上这份文档是有问题的(注:这是我个人造成的问题,我在操作系统中双击解压zip包,自动生成了p13343447_112020_Linux-x86-64目录,而如果命令行下用unzip解压,则不会出现此目录,因此Oracle文档中的描述并没有问题,但是这里主要吐槽下面的报错信息),如果opatch命令写为:

opatch auto /media/sf_PSU -ocmrf /home/grid/ocm.rsp

其中的-ocmrf是另外一个问题,这个OCM的配置文件,根据Readme文档中描述的方法创建即可。

运行以上命令会报错:

Opatch version check failed for oracle home  /u01/app/oracle/product/11.2.0/dbhome_1
Opatch version  check failed
update the opatch version for the failed homes and retry

是的,你没有看错,我也没有贴错,确实报了一模一样的错误(虽然这两个错误都完全不是opatch版本的问题),所以,opatch的报错信息是不可信的,我们必须要去提示的log文件中仔细查看最后的错误信息。

 ZOP-49: Not able to execute the prereq. OPatch cannot inform if the patch satisfies minimum version requirement.
 PatchObject constructor: Input file "/media/sf_PSU/p13343447_112020_Linux-x86-64/etc/config/actions" or "/media/sf_PSU/p13343447_112020_Linux-x86-64/etc/config/inventory" does not exist.

因此,正确的opatch命令应该是:

opatch auto /media/sf_PSU/p13343447_112020_Linux-x86-64 -ocmrf /home/grid/ocm.rsp

3. Oracle软件所在的文件系统剩余空间必须要大于3G,如果不足,会报错:

patch /media/sf_PSU/p13343447_112020_Linux-x86-64/13343447  apply  failed  for home  /u01/app/grid/product/11.2.0/grid
ACFS-9459: ADVM/ACFS is not supported on this OS version: 'error: file /etc/SuSE-release: No such file or directory

可以看到,又是一次很无稽的报错信息,/etc/SuSE-release?拜托,这里只有/etc/redhat-release。

那么,仔细检查log文件,会发现如下的报错:

 Prerequisite check "CheckSystemSpace" failed.
 The details are:
 Required amount of space(3154696080) is not available.
 UtilSession failed: Prerequisite check "CheckSystemSpace" failed.
 Log file location: /u01/app/grid/product/11.2.0/grid/cfgtoollogs/opatch/opatch2012-01-27_18-23-48PM.log

 OPatch failed with error code 73

到此为止,我放弃了在虚拟机中安装PSU 11.2.0.2.5(如果要增加虚拟机中的文件系统剩余空间是非常麻烦的事情),但是我认为解决了磁盘空间问题之后,后面应该不会再有太多问题了。另外,如果在真实环境中这些问题可能都不存在,因为真实环境中文件系统的剩余空间应该远远不止3G,也应该不会有Shared Folder权限的问题,不过目录位置的问题应该还是会遇到,希望这里遇到的问题对将要在产品环境中Apply 11.2.0.2.5 PSU的朋友有帮助。

如果你成功Apply了该版本的Patch,那么也可以留言告诉我你遇到了什么障碍。

Update@2012-02-09
在另外一台测试的Solaris机器中成功apply了最新的11.2.0.3.1 PSU,包括GI和DB的,由于命令跟本文描述的11.2.0.2.5 PSU的更新方法一样,所以记录在此。如果没有本文描述的上述错误,opatch auto还是很简便的。

# export PATH=$PATH:/u02/app/oracle/product/11.2.0/grid/OPatch
# opatch auto /home/oracle/gi_psu_11.2.0.3.1 -ocmrf /home/grid/ocm.rsp
Executing /usr/bin/perl /u02/app/oracle/product/11.2.0/grid/OPatch/crs/patch112.pl -patchdir /home/oracle -patchn gi_psu_11.2.0.3.1 -ocmrf /home/grid/ocm.rsp -paramfile /u02/app/oracle/product/11.2.0/grid/crs/install/crsconfig_params
defined(@array) is deprecated at /u02/app/oracle/product/11.2.0/grid/OPatch/crs/crsconfig_lib.pm line 2149.
        (Maybe you should just omit the defined()?)
defined(@array) is deprecated at /u02/app/oracle/product/11.2.0/grid/OPatch/crs/crsconfig_lib.pm line 2149.
        (Maybe you should just omit the defined()?)
defined(@array) is deprecated at /u02/app/oracle/product/11.2.0/grid/OPatch/crs/crsconfig_lib.pm line 2227.
        (Maybe you should just omit the defined()?)
opatch auto log file location is /u02/app/oracle/product/11.2.0/grid/OPatch/crs/../../cfgtoollogs/opatchauto2012-02-09_01-37-59.log
Detected Oracle Restart install
Using configuration parameter file: /u02/app/oracle/product/11.2.0/grid/crs/install/crsconfig_params
patch /home/oracle/gi_psu_11.2.0.3.1/13348650/custom/server/13348650  apply successful for home  /u01/app/oracle/product/11.2.0/db_1
patch /home/oracle/gi_psu_11.2.0.3.1/13343438  apply successful for home  /u01/app/oracle/product/11.2.0/db_1
Successfully unlock /u02/app/oracle/product/11.2.0/grid
patch /home/oracle/gi_psu_11.2.0.3.1/13348650  apply successful for home  /u02/app/oracle/product/11.2.0/grid
patch /home/oracle/gi_psu_11.2.0.3.1/13343438  apply successful for home  /u02/app/oracle/product/11.2.0/grid
ACFS-9459: ADVM/ACFS is not supported on this OS version: 'Solaris 11 11/11 X86'
CRS-4123: Oracle High Availability Services has been started.

PSU补丁应用完毕以后,数据库会自动启动,接下来需要继续为数据库运行catbundle.sql。

cd $ORACLE_HOME/rdbms/admin
sqlplus / as sysdba
SQL> @catbundle.sql psu apply

检查PSU补丁情况。

$ opatch lsinventory | grep "Patch Set Update"
Patch Description:  "Database Patch Set Update : 11.2.0.3.1 (13343438)"
Patch Description:  "Grid Infrastructure Patch Set Update : 11.2.0.3.1 (13348650)"

$ sqlplus / as sysdba
SQL> select action,comments from registry$history;

ACTION                         COMMENTS
------------------------------ ------------------------------
APPLY                          PSU 11.2.0.3.1

How to use Database File System (DBFS) in Oracle 11gR2

简单的来说,DBFS就是Oracle数据库11gR2中提供的能够在Linux操作系统中将Oracle数据库当成文件系统来使用的功能。在DBFS内部,文件是以SecureFiles LOBs(对比与以前的BasicFiles LOBs)的形式存储在数据表中。

本文简单介绍在Oracle11gR2中使用DBFS的方法。
参考文档:Oracle® Database SecureFiles and Large Objects Developer’s Guide 11g Release 2 (11.2) – 6 DBFS File System Client

本文使用的数据库是Oracle 11.2.0.1,操作系统是Oracle Enterprise Linux 5.3:

$ cat /etc/enterprise-release
Enterprise Linux Enterprise Linux Server release 5.3 (Carthage)
$ uname -r
2.6.18-128.el5

1. 首先需要安装kernel-devel和FUSE包。实际上现在最新的FUSE版本是2.8.5,但是为了防止有兼容性问题,仍然按照文档所述选择了2.7.4版本。kernel-devel包在OEL的安装光盘中就可以找到,如果你的Linux系统中已经安装过,无需再次安装。

# rpm -qa| grep kernel-devel
kernel-devel-2.6.18-128.el5

安装FUSE也同样很简单。
将下载成功的fuse-2.7.4.tar.gz文件解压,生成fuse-2.7.4目录。

# ./configure --prefix=/usr --with-kernel=/usr/src/kernels/`uname -r`-`uname -p`
# make
# make install
# /sbin/depmod
# /sbin/modprobe fuse
# chmod 666 /dev/fuse
# echo "/sbin/modprobe fuse" >> /etc/rc.modules
# chmod +x /etc/rc.modules

2. 在数据库中创建文件系统。创建文件系统的数据库用户至少需要拥有以下权限。

SQL> grant connect, create session, resource, create table, 
create procedure, dbfs_role to kamus;

在$ORACLE_HOME/rdbms/admin目录中执行dbfs_create_filesystem.sql来创建文件系统。其中mytbs为文件系统所在的表空间,dbfs_area为文件系统的名称。

cd $ORACLE_HOME/rdbms/admin
sqlplus kamus
SQL> @dbfs_create_filesystem.sql mytbs dbfs_area

通过观察屏幕显示,可以知道dbfs_create_filesystem.sql实际上是调用了一些package,创建了DBFS文件系统。而这种默认方式对于Securefile LOB的一些特性都是没有启用的,比如压缩,去重,分区,加密等,如果要启用这些特性,可以使用dbfs_create_filesystem_advanced.sql。

--------
CREATE STORE:
begin dbms_dbfs_sfs.createFilesystem(store_name => 'FS_DBFS_AREA', tbl_name =>
'T_DBFS_AREA', tbl_tbs => 'users', lob_tbs => 'users', do_partition => false,
partition_key => 1, do_compress => false, compression => '', do_dedup => false,
do_encrypt => false); end;
--------
REGISTER STORE:
begin dbms_dbfs_content.registerStore(store_name=> 'FS_DBFS_AREA', provider_name
=> 'sample1', provider_package => 'dbms_dbfs_sfs'); end;
--------
MOUNT STORE:
begin dbms_dbfs_content.mountStore(store_name=>'FS_DBFS_AREA',
store_mount=>'dbfs_area'); end;
--------
CHMOD STORE:
declare m integer; begin m := dbms_fuse.fs_chmod('/dbfs_area', 16895); end;

3. 将数据库文件系统mount到操作系统中。

--添加一个新的库目录到库文件加载路径中
# echo "/usr/local/lib" >> /etc/ld.so.conf.d/usr_local_lib.conf
--将必须的库文件link到该目录中
# export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1
# cd /usr/local/lib 
# ln -s $ORACLE_HOME/lib/libclntsh.so.11.1 
# ln -s $ORACLE_HOME/lib/libnnz11.so
# ln -s /usr/lib/libfuse.so
--创建运行时动态库链接
# ldconfig

如果不执行以上步骤,则运行dbfs_client将会报错。

dbfs_client: error while loading shared libraries: libclntsh.so.11.1: cannot open shared object file: No such file or directory

实际上到此为止,DBFS已经可以正常运转了,即使我们不将DBFS挂载到操作系统中的某个目录下,也同样可以通过dbfs_client程序来创建目录,copy文件。

比如用dbfs_client来列出初始的DBFS目录结构。

$ dbfs_client dbfs@localhost:1521/orcl --command  ls -a -R dbfs:/dbfs_area
Password:
dbfs:/dbfs_area/.sfs
dbfs:/dbfs_area/.sfs/content
dbfs:/dbfs_area/.sfs/RECYCLE
dbfs:/dbfs_area/.sfs/snapshots
dbfs:/dbfs_area/.sfs/tools
dbfs:/dbfs_area/.sfs/attributes

创建新目录。

$ dbfs_client dbfs@localhost:1521/orcl --command mkdir dbfs:/dbfs_area/dir1

copy文件。

$ dbfs_client dbfs@localhost:1521/orcl --command cp test.txt dbfs:/dbfs_area/dir1/
Password:
test.txt -> dbfs:/dbfs_area/dir1/test.txt

可以通过以下方式从数据字典中查看DBFS的目录结构和属性。

SQL> select * from table(dbms_dbfs_content.listmounts);
SQL> select * from table(dbms_dbfs_content.listallcontent);
SQL> select * from dbfs_content;
SQL> select * from dbfs_content_properties;

不过为了更加方便使用,我们将DBFS挂载到/dbfs目录中。

--创建挂载点目录,修改目录属主
# mkdir /dbfs
# chown oracle:dba /dbfs
--以oracle用户挂载DBFS文件系统
# su - oracle
$ dbfs_client kamus@dbserver:1521/orcl -o rw,user,direct_io /dbfs

以上命令并没有使用在后台mount DBFS,因此在执行完最后命令的时候,要求输入数据库用户kamus的密码,之后并不会回到命令行状态,这是正常的。

$ dbfs_client kamus@dbserver:1521/orcl -o rw,user,direct_io /dbfs
Password:

如果要以后台的方式mount,则需要执行以下命令,其中pwd.f中保存数据库用户的密码:

$ nohup dbfs_client kamus@dbserver:1521/orcl -o rw,user,direct_io /dbfs < pwd.f &

更安全的方法是使用wallet,方法如下。

--创建wallet目录,该目录位置随意
mkdir $ORACLE_HOME/wallet
--创建Oracle wallet,回车以后会要求指定wallet的密码,要求至少为8个字符。
mkstore -wrl $ORACLE_HOME/wallet -create
--更新$ORACLE_HOME/network/admin/sqlnet.ora文件,添加wallet的位置。
vi $ORACLE_HOME/network/admin/sqlnet.ora
--添加如下行
WALLET_LOCATION =
   (SOURCE =
     (METHOD = FILE)
     (METHOD_DATA =
       (DIRECTORY = /u01/app/oracle/product/11.2.0/dbhome_1/wallet)
     )
   )
SQLNET.WALLET_OVERRIDE = TRUE
--将密码证书添加到wallet中。其中orcl为tnsnames.ora中的条目,kamus为用户名,oracle为密码。
mkstore -wrl $ORACLE_HOME/wallet -createCredential orcl kamus oracle
--添加成功以后,可以通过如下命令查看密码证书
mkstore -wrl $ORACLE_HOME/wallet -listCredential
--挂载DBFS文件系统
dbfs_client -o wallet /@orcl /dbfs

通过wallet方式,如果要挂载不同数据库用户下的DBFS,则需要mkstore -createCredential命令添加多个密码证书,通过不同的tnsnames条目来区分。

--添加scott用户的密码证书
mkstore -wrl $ORACLE_HOME/wallet -createCredential orcl_scott scott tiger
--在tnsnames.ora中添加orcl_scott条目
--挂载DBFS文件系统
dbfs_client -o wallet /@orcl_scott /dbfs

如果要卸载文件系统,则使用:

$ fusermount -u /dbfs

4. 检查文件系统是否已经mount成功。

$ ls -l /dbfs
total 0
drwxrwxrwx 5 root root 0 Apr 12 00:21 dbfs_area

可以看到之前创建的名称为dbfs_area的文件系统已经以目录的形式存在于挂载点/dbfs中了。

5. 创建一个测试目录,直接往目录中copy文件。

$ cd /dbfs/dbfs_area
$ mkdir test
$ echo "A great user experience" > test/dbfs.txt

6. 在数据库中查看该文件是如何存储的。这里我们使用SQL Devloper来更方便地查看LOB数据。

可以注意到:表T_DBFS_AREA是Oracle自动创建的,该表的PATHNAME为文件系统路径,FILEDATA字段为LOB类型,存储真正的文件内容,并且在SQL Developer中也可以看到我们刚才在操作系统中直接echo进dbfs.txt文本文件中的内容了。

再测试一个图片文件。

7. 创建一个新文件系统。

cd $ORACLE_HOME/rdbms/admin
sqlplus kamus/oracle
SQL> @dbfs_create_filesystem.sql mytbs dbfs_pics

8. 新文件系统会立刻以目录的形式出现在操作系统中。

$ ls -l /dbfs
total 0
drwxrwxrwx 4 root root 0 Apr 12 02:20 dbfs_area
drwxrwxrwx 3 root root 0 Apr 12 00:42 dbfs_pics

9. 远程使用sftp从本地机器中上传一个jpg图片,上传到/dbfs/dbfs_pics目录中。

$ ls -l /dbfs/dbfs_pics/
total 33
-rw-r--r-- 1 oracle dba 33565 Apr 12 00:42 zombie2.jpg

10. 在SQL Developer中查看该图片。

11. 查看用户LOB视图,确实是以SecureFile LOBs的形式存储的。

SQL> select table_name,column_name,segment_name,securefile from user_lobs;

TABLE_NAME           COLUMN_NAME          SEGMENT_NAME                   SEC
-------------------- -------------------- ------------------------------ ---
T_DBFS_AREA          FILEDATA             LOB_SFS$_FST_1                 YES
T_DBFS_PICS          FILEDATA             LOB_SFS$_FST_17                YES

至此,完成了最基本的DBFS测试,这是很奇妙的用户体验,不是吗?

【备注1】
在DBFS被使用的时候,也仍然可以正常关闭数据库,这一点与ACFS不同,毕竟这仅仅是通过FUSE框架展现出来的用户接口而已。在关闭数据库以后,再次尝试读取DBFS中的内容,将报IO错误。

$ pwd
/dbfs/dbfs_area/test
$ ls
ls: .: Input/output error

【备注2】
如果在Linux X86-64操作系统中使用dbfs_client,需要额外打上一些Critical Patches,具体参看MOS Note 1150157.1

【备注3】
更多的资料请阅读:

How to resize ACFS and change the mountpoint

关于如何创建ACFS,参看我的上一篇文章:How to create ASM filesystem(ACFS) in Oracle 11gR2

在创建完ACFS之后如果想更改挂载点(mountpoint)以及修改卷的大小,该如何操作呢?

–检查当前ACFS文件系统状态。ACFSDG是ACFS所在的磁盘组,总大小614400M,还有409491M空闲。

$ asmcmd lsdg
State    Type    Rebal  Sector  Block       AU  Total_MB  Free_MB  Req_mir_free_MB  Usable_file_MB  Offline_disks  Voting_files  Name
MOUNTED  EXTERN  N         512   4096  1048576    614400   409491                0          409491              0             N  ACFSDG/
MOUNTED  EXTERN  N         512   4096  1048576      4886     4490                0            4490              0             Y  CRSDG/
MOUNTED  EXTERN  N         512   4096  1048576    488288    90536                0           90536              0             N  DATADG/
MOUNTED  EXTERN  N         512   4096  1048576    223623   221834                0          221834              0             N  FRADG/

–检查ACFSDG上的卷(Volume)。Volume Device是挂载时要指定的设备名称,Usage和Mountpoint仅仅是描述,并不是表明其真正用途和真正的挂载点。
–可以使用asmcmd volset来修改usagestring和mountpath。

$ asmcmd volinfo -G ACFSDG -a
Diskgroup Name: ACFSDG

         Volume Name: ACFSDGVOL1
         Volume Device: /dev/asm/acfsdgvol1-57
         State: ENABLED
         Size (MB): 204800
         Resize Unit (MB): 256
         Redundancy: UNPROT
         Stripe Columns: 4
         Stripe Width (K): 128
         Usage: To Store RMAN backupsets
         Mountpath: We should mount this volume as /backup

–检查ACFS挂载点,可以看到当前Mount Point并不是/backup而是/acfsmounts/acfsdg_acfsdgvol1,后面我们就要修改这个挂载点。

# acfsutil registry -l /dev/asm/acfsdgvol1-57
Device : /dev/asm/acfsdgvol1-57 : Mount Point : /acfsmounts/acfsdg_acfsdgvol1 : Options : none : Nodes : all : Disk Group : ACFSDG : Volume : ACFSDGVOL1 

–创建新的挂载点

# mkdir /backup

–先尝试用asmcmd volresize命令修改卷大小,报ORA-15476错误,实际上这里的意思是说,在卷处于mount状态时,是无法用volresize命令修改卷大小的,必须用acfsutil size命令。volresize命令只能在文件系统被卸载之后才能使用。

ASMCMD> volresize -G acfsdg -s 614400M ACFSDGVOL1
ORA-15032: not all alterations performed
ORA-15476: ACFS volumes must be resized with the 'acfsutil size' operating system command. (DBD ERROR: OCIStmtExecute)

–卸载当前已经挂载的文件系统

# umount -a -t acfs

–修改ACFS Registry,修改这个信息并不会自动挂载文件系统,而只是为了让下次Oracle Clusterware重启的时候可以自动地将文件系统挂载到正确路径下。

# acfsutil registry -d /dev/asm/acfsdgvol1-57
acfsutil registry: successfully removed ACFS volume /dev/asm/acfsdgvol1-57 from Oracle Registry
# acfsutil registry -a /dev/asm/acfsdgvol1-57 /backup
acfsutil registry: mount point /backup successfully added to Oracle Registry
# acfsutil registry -l /dev/asm/acfsdgvol1-57
Device : /dev/asm/acfsdgvol1-57 : Mount Point : /backup : Options : none : Nodes : all : Disk Group : ACFSDG : Volume : ACFSDGVOL1

–在文件系统被卸载之后,尝试使用volresize命令修改大小。报ORA-15041错误,因为我们尝试指定之前在asmcmd lsdg命令中显示的该磁盘组的Total_MB,但是由于ADVM Volume在创建时会有额外的空间开销,因此报空间不足。当然,如果这里我们将大小降低1G左右,volresize命令是可以运行成功的。本例中在后面选择使用acfsutil size来修改大小。

$ asmcmd volresize -G acfsdg -s 614400M ACFSDGVOL1
ORA-15032: not all alterations performed
ORA-15041: diskgroup "ACFSDG" space exhausted (DBD ERROR: OCIStmtExecute)

–手动挂载文件系统到新目录下。

# mount -v -t acfs /dev/asm/acfsdgvol1-57 /backup
mount.acfs: volume: /dev/asm/acfsdgvol1-57, mount point: /backup
mount.acfs: options: rw
mount.acfs: verbose option specified
mount.acfs: command string: /bin/mount -i -t acfs -o ,rw /dev/asm/acfsdgvol1-57 /backup -v.
/dev/asm/acfsdgvol1-57 on /backup type acfs (rw)

–修改挂载点属主

# chown oracle:oinstall /backup 

–acfsutil size命令可以在文件系统仍然被使用的时候进行扩容,+/-符号表示要在当前基础上增加或者减少多少,这比volresize命令更灵活。

# acfsutil size +400000M /backup
acfsutil size: new file system size: 634312982528 (604928MB)
# acfsutil size +8000M /backup
acfsutil size: new file system size: 642902917120 (613120MB)
# acfsutil size -3000M /backup
acfsutil size: new file system size: 639950127104 (610304MB)