Skip to content

Oracle 排障配置与调整 - 16. page

ASM 实例报错 04031

04031这个错误算是老生常谈了,shared pool不足。在asm实例中也有shared pool,在内存不足时候也会报错04031,碰到这种情况怎么处理?

今天一个客户碰到了这个错误,一般来讲默认的asm实例大小为272M,足够asm使用,而客户是这个节点上面部署了监控asm实例的脚本,跑了一年多出现了今天的情况,初步估计是因为asm的shared pool缓存了太多的这个脚本的sql(解析版本多),导致了今天的情况出现,出现这种情况有2种处理办法:

 

1.增加sga的大小

10g中通过修改sga_max_size的方式(需要重启asm)

11g中通过修改memory_max_target和memory_target(需要重启asm)

 

2.刷共享池

通过刷共享池的方式来解决04031,但是这样会对dbinstance有影响。

 

具体命令为:

alter system flush shared_pool;

具体参考MOS 1370925.1

Dataguard 跨平台支持列表

oracle支持dataguard 跨平台,但是有不少限制,具体参考以下列表。

 

PLATFORM_ID PLATFORM_NAME
Release name
PLATFORM_IDs supported within the same Data Guard configuration when using Data Guard Redo Apply (Physical Standby)
2 Solaris[tm] OE (64-bit)
Solaris Operating System (SPARC) (64-bit)
2
6 – This is not supported due to issues reported in Bug 12702521
3 HP-UX (64-bit)
HP-UX PA-RISC
3
4 – Oracle 10g onward, see Support Note: 395982.1 and Note:414043.1
4 HP-UX IA (64-bit)
HP-UX Itanium
4
3 – Oracle 10g onward, see Support Notes Note: 395982.1 and Note:414043.1
5 HP Tru64 UNIX
HP Tru64 UNIX
5
6 IBM AIX on POWER Systems (64-bit) 2 – This is not supported due to issues reported in Bug 12702521
6
7 Microsoft Windows (32-bit)
Microsoft Windows (x86)
7
8, 12  – Oracle 10g onward, see Support Note: 414043.1
10 – Oracle 11g onward, requires Patch 13104881
11, 13 – Oracle 11g onward, see Support Note: 414043.1, also requires Patch 13104881
8 Microsoft Windows IA (64-bit)
Microsoft Windows (64-bit Itanium)
7 – Oracle 10g onward, see Support Note: 414043.1
8
12 – Oracle 10g onward
11, 13 – Oracle 11g onward, requires Patch 13104881
9 IBM zSeries Based Linux
z/Linux
9
18 (64-bit zSeries only)
10 Linux (32-bit)
Linux x86
7 – Oracle 11g onward, requires Patch 13104881
10
11, 13 – Oracle 10g onward, see Support Note: 414043.1
11 Linux IA (64-bit)
Linux Itanium
10 – Oracle 10g onward, see Support Note: 414043.1
11
13 – Oracle 10g onward
7 – Oracle 11g onward, see Support Note: 414043.1, also requires Patch 13104881
8, 12 – Oracle 11g onward, requires Patch 13104881
12 Microsoft Windows 64-bit for AMD
Microsoft Windows (x86-64)
7 – Oracle 10g onward, see Support Note Note: 414043.1
8 – Oracle 10g onward
12
11, 13 – Oracle 11g onward, requires Patch 13104881
13 Linux 64-bit for AMD
Linux x86-64
7 – Oracle 11g onward, see Support Note: 414043.1, also requires Patch 13104881
10 – Oracle 10g onward, see Support Note Note: 414043.1
11 – Oracle 10g onward
8, 12 – Oracle 11g onward, requires Patch 13104881
13
20 – Oracle 11g onward
15 HP Open VMS
HP OpenVMS Alpha
HP IA OpenVMS
OpenVMS Itanium
15
16 Apple Mac OS
Mac OS X Server
16
17 Solaris Operating System (x86)
Solaris Operating System (x86)
17
20 – Oracle 10g onward, see Support Note: 414043.1
18 IBM Power Based Linux
Linux on Power
9 (64-bit zSeries only)
18
20 Solaris Operating System (AMD64)
Solaris Operating System (x86-64)
13 – Oracle 11g onward
17 – Oracle 10g onward, see Support Note: 414043.1
20

浅谈Goldengate关于进程Lag延时大的优化

最近临时接手一个ogg的项目,前面的兄弟没处理好,算是临危而上了。当时是这种情况,ogg的初始化完成了,但是发现复制进程的延时有100多个小时,而且越积越多,但是进程还是在正常允许没有hang住,根据这个情况根据数据库和ogg的角度提出和执行了一些优化上的处理事宜,具体如下:

首先延时是一个相对的代表当前数据同步处理情况,相对主库运行时间段的一种判断,也是OGG提供给我们当前进行的工作进度展示,影响Goldnenate进程lag的因素有哪些?

具体我统计如下:

1.OGG bug,不能正常显示lag信息,由于时区设置不正确,或者本身程序等造成

2.OGG 源端抽取进程延时大,这个时候主要是取决与当前主机CPU,IO,在硬件(上述任1)资源达到超负荷时候,对抽取进程的处理就会挂起乃至延时,造成lag过大或者是显示不正确,或者是抽取开始的scn距离当前的主库scn有时间的差距。

3.OGG 源端传送进程延时大,这个时候主要是取决于主机的CPU,IO,NETWORK,在除了与2中的硬件资源有关之外,还跟OGG传送的网卡,生产到目的端网络情况(包括网络通信长度,网络繁忙度, 网络有效负荷等),生产与目的端防火墙对发送包的限制情况。

举些例子,如果你的日志量很大,但是你的网卡为百M网卡,你传送需求是20M/s,传送速率只有理论的10/S,这时候延时显而易见就出来了,你每秒就有10m的延时,相当于1s就积累1s的延时。
比如传输长度,光纤输出平均1公里增加延时1ms,这个时候比如吉林长春到北京亦庄的光纤是经过了1000公里,那么这里1000*0.001=1s,这是理论的情况下最小的延时。
再接着是防火墙,还有无线网络的考虑情况,这些跟网络传输环境息息相关的方面都需要考虑进去。
4.OGG 目标端lag很大,跟目标端的cpu,io有关,这个时候目标端的cpu压力主要来自于3方面:系统运行,数据库运行,OGG运行;IO压力主要来自于OGG以及数据库的日志写和读,那么repliact进程延时大了主要是什么情况?

    4.1.io不够,cpu够,你数据库有能力1秒能写200M数据,但是你存储io只能写100M,这个时候就积累延时了
    4.2.io够了,cpu不够,这个时候你也会发现有延时,因为你处理速度远远低于源端传过来的数据的速度,这个时候延时也就积累了
    4.3.io够了,cpu够了,这个时候你硬件很ok,但是你的延时很大,这个就是进程积累的日志过多;

数据库性能问题,OGG性能问题就和看病一样,需要对症下药,如果诊断错了,你开的药就错了,出现的结果就是病没治好,有可能身体本身器官负载还更大了.在这个项目中的情况,和我上述描述的症状对比起来,在多次诊断中,我比较倾向4.1,4.2,4.3的综合类型,就是目标端replicat应用日志的速度无法追上(4.1,4.2),而且在初始化完成后本身在目标端积累了过多的日志(4.3)。

那又怎么处理?对症下药。优化资源使用,提高数据库的处理速度是我们要做的事情。那么怎么处理?根据情况可以考虑下面的2种方式来做

一:提高目标端Oracle处理速度

1.关闭备库的日志补全级别,关闭备库的强制日志模式,减少redo产生,降低io。
2.置备库为noarchive(非归档模式),减少archive过程产生的io。
3.提高备库服务器的内存大小,为Oracle设置更大的buffer cache,shared pool,减少VMM控制的整体的换页频率所带来的对cpu和io的额外负荷。
4.确认异步IO是否开启。未开启的过程请打开服务器的aio,aix确认如下lsdev -Cc aio
5.提高PGA的大小,为多个的repliacat进程们提供足够的缓存区域。
6.对目标端ogg的接收源端发来的data文件 和 oracle本身的数据文件错开到不同的(存储级别)vg上面,以避免disk hot的情况出现,进而提高io效率
7.对无查询,存插入更新(全表)的对象的索引进行删除

二:从业务逻辑上拆分繁忙的延时大复制进程

角度1:工作量最小,但是统计会有一定误差

在局部进程延时大的时候,可能是这种情况,业务处理的核心压力都集中在一些对象上面,而这些对象都被安排设置到一个进程中,这个时候大部分的日志都集中在这个进程中,出现了这个进程很忙,其他进程很闲,类似多点闲单点热的情况,如果这个时候硬件资源满足情况下,可以从业务逻辑上去拆分这个进程,比如这次宋经理根据应用开发商的提供的表的更改频率表按照等级来拆分进程,按照表的繁忙度把热点表们平摊到2个进程中。而周五我的建议是全部平摊出去,这样效果才会明显,而根据文档显示宋经理已经按照应用商提供的将热点表全部平摊到各个进程中。
在这方面,我方从数据库角度提出建议,应用从业务角度划分出来的表可以从数据库对应DML操作的频率记录上进行check对应。因为存在一种情况,应用提供商提供的是表的操作频率,比如查询,更新,插入,删除都是在一起统计的,从细化上我们需要的表的更新,插入,删除方面的统计信息,这类信息可以通过oracle 实例中的ALL_TAB_MODIFICATIONS表进程查询数据库中所有对象的delete,insert,update的频率,根据频率高的进行排序,再对频率高的前100,或者200的表进行拆分,这样的效果可能会更理想,具体语句如下:

select TABLE_OWNER,TABLE_NAME,INSERTS,UPDATES,DELETES from ALL_TAB_MODIFICATIONS ORDER BY 3,4,5;

或者

select TABLE_OWNER,TABLE_NAME,INSERTS+UPDATES+DELETES "ALL_DML_COUNTS" from ALL_TAB_MODIFICATIONS ORDER BY 3;

角度2:工作量较大,但是统计效果精准

表的DML频率并无法估算到具体产生的redo量,理论上redo的产生量越大,对应的操作涉及的数据(比如表的字段多,数据量大)就越多,所以从这个角度上讲,我们是要找到redo量产生多的那些表,这种情况下就需要用到logmnr工作,通过对归档日志的挖掘分析,开对ogg的部署进行决策支持,在当前项目,这个角度比较不倾向实际,但是可以作为一个参考方向。

整理的DBA常用脚本

oracle用户权限检查
1. 系统权限记录在 dba_sys_privs 视图中:
select grantee, privilege, admin_option
from dba_sys_privs
where grantee = ‘USERNAME’ ;
2. 角色权限记录在 dba_role_privs 视图中:
select grantee, granted_role, admin_option
from dba_role_privs
where grantee = ‘USERNAME’ ;
3. 对象权限记录在 dba_tab_privs 视图中,虽然视图名看起来像是表权限,但是实际包含了包,存储过程等等对象级的权限:
select grantee, owner || ‘.’ || table_name obj_name, privilege, grantable
from dba_tab_privs
where grantee = ‘USERNAME’;
4. 其他还有部分权限,如表空间的quota权限,记录在 dba_ts_quota中:
select username,
tablespace_name,
bytes / 1024 / 1024 “used space (m)”,
decode(decode(max_bytes, -1, 0, max_bytes) / 1024 / 1024,
0,
‘unlimited’,
max_bytes / 1024 / 1024) “max space(m)”,
blocks used_blocks,
max_blocks
from dba_ts_quotas
where username = ‘USERNAME’;
select * from session_privs; 当前用户拥有的权限
SELECT * FROM DBA_SYS_PRIVS; 查询每个用户的权限
锁的检查
select b.owner,
b.object_name,
l.SESSION_ID,
DECODE(L.LOCKED_MODE,
0,
‘None’,
1,
‘Null’,
2,
‘Row-S (SS)’,
3,
‘Row-X (SX)’,
4,
‘Share’,
5,
‘S/Row-X (SSX)’,
6,
‘Exclusive’,
TO_CHAR(L.LOCKED_MODE)) MODE_HELD,
s.USERNAME
from dba_objects b, v$locked_object l, V$SESSION S
where b.object_id = l.object_id
and l.SESSION_ID = s.SID
查看一个长查询的进度
SELECT *
FROM ( select username,opname,sid,serial#,
context,b.sql_text,sofar,totalwork,
round(sofar/totalwork*100,2) “% Complete”,
elapsed_seconds
from v$session_longops , v$sql b
where sql_hash_value=b.hash_value
and sql_address = address
and totalwork <> 0
)
WHERE “% Complete” <> 100 ;
查看ACTIVE SESSION的等待事件
select a.event,
sum(decode(wait_Time, 0, 0, 1)) “Prev”,
sum(decode(wait_Time, 0, 1, 0)) “Curr”,
count(*) “Tot”
from v$session_wait a, v$session b
where a.sid = b.sid
and b.status = ‘ACTIVE’
group by a.event
— having count(*) > 10
order by 4;

在某个用户下找所有的索引
select user_indexes.table_name, user_indexes.index_name,uniqueness, column_name
from user_ind_columns, user_indexes
where user_ind_columns.index_name = user_indexes.index_name
and user_ind_columns.table_name = user_indexes.table_name
order by user_indexes.table_type, user_indexes.table_name,
user_indexes.index_name, column_position;
通过DBMS_METADATA包得到对象的DLL语句
a.获取单个的建表和建索引的语法,其他对象类似:
select dbms_metadata.get_ddl(‘TABLE’,’TABLE_NAME’,’TABLE_OWNER’) from dual;
select dbms_metadata.get_ddl(‘INDEX’,’INDEX_NAME’,’INDEX_OWNER’) from dual;

b.获取一个SCHEMA下的所有建表的语法,以scott为例,其他对象类似:
SELECT DBMS_METADATA.GET_DDL(‘TABLE’, u.table_name, u.owner) || ‘;’
FROM DBA_TABLES u
where owner = ‘SCOTT’ ;
查看回滚段名称及大小
select segment_name,
tablespace_name,
r.status,
(initial_extent / 1024) InitialExtent,
(next_extent / 1024) NextExtent,
max_extents,
v.curext CurExtent
From dba_rollback_segs r, v$rollstat v
Where r.segment_id = v.usn(+)
order by segment_name;

查看表空间的名称及大小
select t.tablespace_name, round(sum(bytes / (1024 * 1024)), 0) ts_size
from dba_tablespaces t, dba_data_files d
where t.tablespace_name = d.tablespace_name
group by t.tablespace_name;

查看数据库的版本
Select version
FROM Product_component_version
Where SUBSTR(PRODUCT, 1, 6) = ‘Oracle’;

查看数据库的创建日期和归档方式
Select Created, Log_Mode From V$Database;

查看还没提交的事务
select * from v$locked_object;
select * from v$transaction;
查找object为哪些进程
select p.spid,
s.sid,
s.serial# serial_num,
s.username user_name,
a.type object_type,
s.osuser os_user_name,
a.owner,
a.object object_name,
decode(sign(48 – command),
1,
to_char(command),
‘Action Code #’ || to_char(command)) action,
p.program oracle_process,
s.terminal terminal,
s.program program,
s.status session_status
from v$session s, v$access a, v$process p
where s.paddr = p.addr
and s.type = ‘USER’
and a.sid = s.sid
and a.object = ‘EMP’
order by s.username, s.osuser
怎样计算一个表占用的空间的大小?
select owner,
table_name,
NUM_ROWS,
BLOCKS * AAA / 1024 / 1024 “Size M”,
EMPTY_BLOCKS,
LAST_ANALYZED
from dba_tables
where table_name = ‘XXX’;

注意:执行以上语句前要先对表做统计分析

select sum(a.bytes) / 1024 * 1024 “size”
from dba_extents a
where a.segment_name = ‘GOV_FDDBR’
select a.bytes / 1024 * 1024 “size”, (a.blocks * 8192) / 1024 * 1024 “da”
from dba_segments a
where a.segment_name = ‘GOV_FDDBR’
如何查看最大会话数
SELECT * FROM V$PARAMETER WHERE NAME LIKE ‘proc%’;
SQL>
SQL> show parameter processes

NAME TYPE VALUE
———————————— ——- ——————————
aq_tm_processes integer 1
db_writer_processes integer 1
job_queue_processes integer 4
log_archive_max_processes integer 1
processes integer 200

这里为200个用户。

select * from v$license;
其中sessions_highwater纪录曾经到达的最大会话数
如何在Oracle服务器上通过SQLPLUS查看本机IP地址

select sys_context(‘userenv’,’ip_address’) from dual;

如何将表、索引移动表空间
ALTER TABLE TABLE_NAME MOVE TABLESPACE_NAME;
ALTER INDEX INDEX_NAME REBUILD TABLESPACE TABLESPACE_NAME;
如何才能得知系统当前的SCN号
select max(ktuxescnw * power(2, 32) + ktuxescnb) from x$ktuxe;
如何在字符串里加回车
select ‘Welcome to visit’||chr(10)||’www.CSDN.NET’ from dual;
如何将小表放入keep池中
alter table xxx storage(buffer_pool keep);
如何查询做比较大的排序的进程?
SELECT b.tablespace,
b.segfile#,
b.segblk#,
b.blocks,
a.sid,
a.serial#,
¡¡ a.username,
a.osuser,
a.status ¡¡
FROM v$session a, v$sort_usage b ¡¡
WHERE a.saddr = b.session_addr ¡¡
ORDER BY b.tablespace, b.segfile#, b.segblk#, b.blocks;

如何删除重复记录?
DELETE FROM TABLE_NAME
WHERE ROWID != (SELECT MAX(ROWID)
FROM TABLE_NAME D
WHERE TABLE_NAME.COL1 = D.COL1
AND TABLE_NAME.COL2 = D.COL2);
如何回滚段的争用情况
select name, waits, gets, waits / gets “Ratio”  
from v$rollstat C, v$rollname D  
where C.usn = D.usn;
如何监控表空间的 I/O 比例
select B.tablespace_name name,
B.file_name “file”,
A.phyrds pyr,
  A.phyblkrd pbr,
A.phywrts pyw,
A.phyblkwrt pbw  
from v$filestat A, dba_data_files B  
where A.file# = B.file_id  
order by B.tablespace_name;

如何监控文件系统的 I/O 比例
Select substr(C.file#, 1, 2) “#”,
substr(C.name, 1, 30) “Name”,
C.status,
C.bytes,
D.phyrds,
D.phywrts  
from v$datafile C, v$filestat D  
where C.file# = D.file#;
如何在某个用户下找所有的索引
select user_indexes.table_name,
user_indexes.index_name,
uniqueness,
column_name  
from user_ind_columns, user_indexes  
where user_ind_columns.index_name = user_indexes.index_name
and user_ind_columns.table_name = user_indexes.table_name  
order by user_indexes.table_type,
user_indexes.table_name,
 user_indexes.index_name,
column_position;
如何监控 SGA 中字典缓冲区的命中率
select parameter,
gets,
Getmisses,
getmisses / (gets + getmisses) * 100 “miss ratio”,
 (1 – (sum(getmisses) / (sum(gets) + sum(getmisses)))) * 100 “Hit ratio”  
from v$rowcache  
where gets + getmisses <> 0  
group by parameter, gets, getmisses;
如何监控 SGA 中共享缓存区的命中率,应该小于1%
select sum(pins) “Total Pins”,
sum(reloads) “Total Reloads”,
 sum(reloads) / sum(pins) * 100 libcache  
from v$librarycache;

select sum(pinhits – reloads) / sum(pins) “hit radio”,
sum(reloads) / sum(pins) ¡¡¡¡”reload percent” ¡¡
from v$librarycache;
监控 SGA 中重做日志缓存区的命中率,应该小于1%
SELECT name,
gets,
misses,
immediate_gets,
immediate_misses,
Decode(gets, 0, 0, misses / gets * 100) ratio1,
Decode(immediate_gets+immediate_misses,0,0, immediate_misses / (immediate_gets + immediate_misses) * 100) ratio2  
FROM v$latch
WHERE name IN (‘redo allocation’, ‘redo copy’);

监控内存和硬盘的排序比率,最好使它小于 .10,增加 sort_area_size
SELECT name, value
FROM v$sysstat
WHERE name IN (‘sorts (memory)’, ‘sorts(disk)’);
如何监控当前数据库谁在运行什幺SQL语句?
SELECT osuser, username, sql_text
from v$session a, v$sqltext b  
where a.sql_address = b.address
order by address, piece;
如何查看碎片程度高的表?
SELECT segment_name table_name, COUNT(*) extents  
FROM dba_segments
WHERE owner NOT IN (‘SYS’, ‘SYSTEM’)
GROUP BY segment_name  
HAVING COUNT(*) = (SELECT MAX(COUNT(*))
FROM dba_segments
GROUP BY segment_name);
如何知道表在表空间中的存储情况?
select segment_name, sum(bytes), count(*) ext_quan
from dba_extents
where tablespace_name = ‘&tablespace_name’
and segment_type = ‘TABLE’
group by tablespace_name, segment_name;
如何知道索引在表空间中的存储情况?
select segment_name, count(*)
from dba_extents
where segment_type = ‘INDEX’
and owner = ‘&owner’  
group by segment_name;

如何知道使用CPU多的用户session?
Select a.sid,spid,status,
substr(a.program,1,40)
prog,a.terminal,osuser,value/60/100 value
  from v$session a,v$process b,v$sesstat c
  where c.statistic#=11 and c.sid=a.sid and a.paddr=b.addr
order by value desc;
物理读和内存读较高SQL
SELECT t.HASH_VALUE,
t.EXECUTIONS,
t.DISK_READS,
round(t.DISK_READS / t.EXECUTIONS) AS perDiskReads,
t.BUFFER_GETS,
round(t.BUFFER_GETS / t.EXECUTIONS) AS perBufferReads,
t.ELAPSED_TIME,
round(t.ELAPSED_TIME / t.EXECUTIONS) AS perElayTime,
t.CPU_TIME,
round(t.CPU_TIME / t.EXECUTIONS) AS perCpuTime,
t.FIRST_LOAD_TIME,
t.SQL_TEXT
FROM v$sql t
WHERE (t.DISK_READS / t.EXECUTIONS > 500 OR
t.BUFFER_GETS / t.EXECUTIONS > 20000)
AND t.EXECUTIONS > 0
ORDER BY 6 DESC;
查看低效率的SQL语句
SELECT EXECUTIONS,
DISK_READS,
BUFFER_GETS,
ROUND((BUFFER_GETS – DISK_READS) / BUFFER_GETS, 2) Hit_radio,
ROUND(DISK_READS / EXECUTIONS, 2) Reads_per_run,
SQL_TEXT
FROM  V$SQLAREA    
WHERE EXECUTIONS > 0   
AND  BUFFER_GETS > 0   
AND (BUFFER_GETS – DISK_READS) / BUFFER_GETS < 0.8    ORDER BY EXECUTIONS DESC 或者 select executions exec, loads loads, parse_calls parse, disk_reads reads, buffer_gets gets, rows_processed rows_proc, sorts sorts, sql_text from v$sqlarea order by &sortkey desc; 找出oracle中从没有使用的索引 set pages 999; set heading off; spool run_monitor.sql select 'alter index '||owner||'.'||index_name||' monitoring usage;' from dba_indexes where owner not in ('SYS','SYSTEM','PERFSTAT') spool off; @run_monitor 等待一段时间直到在数据库上运行了足够多的SQL语句以后,然后你就可以查询新的V$OBJECT_USAGE视图。 Select index_name,table_name,mon,used from v$object_usage; 在V$OBJECT_USAGE有一列被称作USED,它的值是YES或者NO。不幸的是,它不会告诉你Oracle使用了这个索引多少次,但是这个工具对于找出没有使用的索引还是很有用的。 自己编写的脚本 select c.SID,c.STATUS,s.NAME,b.VALUE from v$statname s, v$sesstat b, v$session c where s.STATISTIC# = b.STATISTIC# and b.SID = c.SID and b.sid=&sid and s.NAME in ('consistent gets','physical reads','parse count (total)','parse count (hard)') V$sql:查询一条sql执行时间及消耗的cpu时间,被执行及被分析的次数 Parse_calls, Executions Cpu_time, Elapsed_time Alter system flush shared_pool 清空共享池

Oracle Database PSU与CPU的区别

最近不少人问我关于CPU以及PSU的区别问题,我把这个问题的解释发到这里来,具体如下:

转载自:http://www.cnblogs.com/ebs-blog/archive/2011/07/28/2167232.html

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)

另外的方法是查看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]