Notes for Oracle Database PSU/CPU

1. 什么是PSU/CPU?
CPU: Critical Patch Update
Oracle对于其产品每个季度发行一次的安全补丁包,通常是为了修复产品中的安全隐患。

PSU: Patch Set Updates
Oracle对于其产品每个季度发行一次的补丁包,包含了bug的修复。Oracle选取被用户下载数量多的,并且被验证过具有较低风险的补丁放入到每个季度的PSU中。在每个PSU中不但包含Bug的修复而且还包含了最新的CPU。

2. 如何查找最新的PSU?
每个数据库版本都有自己的PSU,PSU版本号体现在数据库版本的最后一位,比如最新的10.2.0.5的PSU是10.2.0.5.3,而11.2.0.2的最新PSU则是11.2.0.2.2。
MOS站点中Oracle Recommended Patches — Oracle Database [ID 756671.1] 文档中查到各个产品版本最新的PSU。
如果你记不住这个文档号,那么在MOS中以“PSU”为关键字搜索,通常这个文档会显示在搜索结果的最前面。

注意:必须购买了Oracle基本服务获取了CSI号以后才有权限登陆MOS站点。

3. 如何正确安装PSU?
每个PSU安装包中都包含一个README.html文档,其中描述了如何安装该PSU,有些PSU是可以直接安装的,而有些PSU则必须要求安装了上一个版本的PSU之后才能继续安装。比如对于10.2.0.4版本的数据库来说,PSU 10.2.0.4.4可以直接安装在最原始的10.2.0.4.0版本中,而最新的PSU 10.2.0.4.8则必须要求先安装10.2.0.4.4。这些信息在README.html中都可以找到,所以请仔细阅读该文档。

通常安装PSU是比较简单的,步骤如下:
1) 安装PSU需要使用到opatch,在README.html中有描述该PSU需要的最低版本opatch,如果当前opatch版本过低,则需要先下载Patch 6880880,该Patch中包含最新的opatch,只需要解压覆盖原先的$ORACLE_HOME/OPatch目录即可。

查看当前的opatch版本,可以使用opatch version命令。

$ opatch version
Invoking OPatch 10.2.0.5.2

OPatch Version: 10.2.0.5.2

OPatch succeeded.

2)安装PSU,请仔细阅读README.html,确认安装命令,通常是简单的opatch apply。

opatch apply

3)更新数据库,将修改过的SQL文件应用到数据库中,很多DBA在执行完上述安装命令以后就不再进行这一步,那么实际上PSU是没有完整安装的。

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

注意:如果PSU是overlay PSU,比如10.2.0.4.8,则需要执行@catbundle.sql opsu apply,同样这些在README.html中都有详细描述。

4)重新编译CPU相关视图。该步骤在一个数据库上永远只需要执行一次,是为了完成在2008年1月份第一次发布CPU补丁时的后续工作,如果在安装以前的PSU或者CPU时执行过这个步骤那么就可以无需再次执行,另外,即使不执行该步骤,数据库也是正常运行的,只不过意味着2008年1月份的CPU补丁没有正常结束安装。

cd $ORACLE_HOME/cpu/view_recompile
sqlplus / as sysdba
SQL> @recompile_precheck_jan2008cpu.sql
SQL> SHUTDOWN IMMEDIATE
SQL> STARTUP UPGRADE
SQL> @view_recompile_jan2008cpu.sql
SQL> SHUTDOWN;
SQL> STARTUP;
SQL> QUIT

注意:该步骤由于需要重新编译大量视图,因此要启动数据库到upgrade状态才可以完成。也就是将引起停机时间。

4. 如何确认当前数据库已经安装了什么PSU/CPU?
无论是从V$VERSION或者DBA_REGISTRY或者PRODUCT_COMPONENT_VERSION视图中,都无法查找到PSU的信息,这些视图中始终显示的是最原始的版本,比如10.2.0.4.0。

最常用的方法是使用opatch命令。在打完最新的PSU 10.2.0.4.8的10.2.0.4数据库中会有以下显示。

$ opatch lsinventory -bugs_fixed | grep -i 'DATABASE PSU'
9654991    11724977  Wed May 25 16:37:17 CST 2011   DATABASE PSU 10.2.0.4.5 (REQUIRES PRE-REQUISITE 
9952234    11724977  Wed May 25 16:37:17 CST 2011   DATABASE PSU 10.2.0.4.6 (REQUIRES PRE-REQUISITE 
10248636   11724977  Wed May 25 16:37:17 CST 2011   DATABASE PSU 10.2.0.4.7 (REQUIRES PRE-REQUISITE 
11724977   11724977  Wed May 25 16:37:17 CST 2011   DATABASE PSU 10.2.0.4.8 (REQUIRES PRE-REQUISITE 
8576156    9352164   Wed May 25 15:10:48 CST 2011   DATABASE PSU 10.2.0.4.1 (INCLUDES CPUJUL2009)
8833280    9352164   Wed May 25 15:10:48 CST 2011   DATABASE PSU 10.2.0.4.2 (INCLUDES CPUOCT2009)
9119284    9352164   Wed May 25 15:10:48 CST 2011   DATABASE PSU 10.2.0.4.3 (INCLUDES CPUJAN2010)
9352164    9352164   Wed May 25 15:10:48 CST 2011   DATABASE PSU 10.2.0.4.4 (INCLUDES CPUAPR2010)

备注:在11gR2中,opatch lsinventory命令就可以显示已经打过的PSU名称了,而无需再增加-bug_fixed参数。

$ 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)"

另外的方法是查看registry$history表。

SQL> select action,comments from registry$history;

ACTION			       COMMENTS
------------------------------ --------------------
APPLY			       PSU 10.2.0.4.4
APPLY			       PSU 10.2.0.4.8
CPU			       view recompilation

注意:该表的内容是在上述安装PSU步骤的第三步中运行catbundle.sql才会插入的,因此如果该步骤忘记执行,则此表中无记录。因此我们在作数据库健康检查的时候不但要用opatch检查当前数据库最新的PSU补丁,也要检查registry$history表,以确认其它DBA是否正确地完成了PSU的安装。

如果多个PSU的安装都忘记了执行上述第三步,可以通过以下方法依次补作。

$ ls -l $ORACLE_HOME/psu
total 0
drwxrwxrwx   2 oracle     dba             96 Oct 16  2010 10.2.0.4.4
drwxrwxrwx   2 oracle     dba             96 Oct 16  2010 10.2.0.4.5
$sqlplus / as sysdba
SQL> @?/psu/10.2.0.4.4/catpsu.sql
SQL> @?/psu/10.2.0.4.5/catopsu.sql

更多关于CPU的信息,可以参看:Maclean的了解Oracle Critical Patch Update

5. 参考文档。
Oracle Recommended Patches — Oracle Database [ID 756671.1]
Patch Set Updates for Oracle Products [ID 854428.1]
Introduction To Oracle Database catbundle.sql [ID 605795.1]
How to confirm that a Critical Patch Update (CPU) has been installed in Linux / UNIX [ID 821263.1]

How to change I/O scheduler in Linux

Updated@2015/12/15

为什么可能会去修改Linux I/O Scheduler (elevator)?以及什么是I/O Scheduler,应该如何为数据库系统选择合适的I/O Scheduler?可以参看以下文章。

那么如果我们确认要修改I/O scheduler,该如何进行? 参考 – How to change default I/O scheduler?

大体上来说就是,比如像修改I/O scheduler为dealine:

  1. 在RHEL4/OEL4中,修改/boot/grub/grub.conf文件,添加elevator=deadline,重启生效,比如:
    title Red Hat Enterprise Linux Server (2.6.18-8.el5)
    root (hd0,0)
    kernel /vmlinuz-2.6.18-8.el5 ro root=/dev/vg0/lv0 elevator=deadline
    initrd /initrd-2.6.18-8.el5.img
  2. 在RHEL5/OEL5以及之后的版本中(比如RHEL6和RHEL7),可以针对每块磁盘制定I/O Scheduler,修改完毕立刻生效,比如:
    --当前是是noop
    # cat /sys/block/sda1/queue/scheduler 
    [noop] anticipatory deadline cfq
    --修改为deadline
    # echo 'deadline'>/sys/block/sda1/queue/scheduler 
    --立刻生效
    # cat /sys/block/sda1/queue/scheduler 
    noop anticipatory [deadline] cfq 

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 -sORACLE_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 -wrlORACLE_HOME/wallet -create
--更新ORACLE_HOME/network/admin/sqlnet.ora文件,添加wallet的位置。
viORACLE_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 -wrlORACLE_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】
更多的资料请阅读: