翠花
周二陪老婆去看话剧《翠花》上海首演,主要还是看邓超。上戏剧院坐的满满的,女生居多,男生大部分是和我一样是陪客。
估计大部分都是邓超的粉丝。我对明星不感冒,不过看下来,邓超确实演得好,而且也没有因为自己大牌而偷懒,戏份很多。
这部戏如果没有邓超的表演只能算一般般。孙俪没现身,来的是孙俪她妈……

周二陪老婆去看话剧《翠花》上海首演,主要还是看邓超。上戏剧院坐的满满的,女生居多,男生大部分是和我一样是陪客。
估计大部分都是邓超的粉丝。我对明星不感冒,不过看下来,邓超确实演得好,而且也没有因为自己大牌而偷懒,戏份很多。
这部戏如果没有邓超的表演只能算一般般。孙俪没现身,来的是孙俪她妈……

这是在一次恢复演习中偶然发现的一个有趣的问题。
当LMT表空间中文件被offline后,如果该文件中包含有segment header,那么从dba_extents中不能看到该segment。
来看一个测试:
SQL> select file_id from dba_data_files where tablespace_name=’TEST’;
FILE_ID
———-
10
11SQL> create table eagle_fan(x int) tablespace test;
Table created.
SQL> select header_file from dba_segments where segment_name=’EAGLE_FAN’ and owner=’SYS’;
HEADER_FILE
———–
10SQL> select extent_id ,file_id from dba_extents where segment_name=’EAGLE_FAN’ and owner=’SYS’;
EXTENT_ID FILE_ID
———- ———-
0 10SQL> select distinct segment_name from dba_extents where file_id=10;
SEGMENT_NAME
——————————————————————————–
TEST
EAGLE_FANSQL> alter database datafile 10 offline ;
Database altered.
SQL> select extent_id ,file_id from dba_extents where segment_name=’EAGLE_FAN’ and owner=’SYS’;
SQL> select distinct segment_name from dba_extents where file_id=10;
SEGMENT_NAME
——————————————————————————–
TESTno rows selected
可以看到datafile 10被offline后,从dba_extents已经看不到该segment。推想而知,对于LMT tablespace,dba_extents会读取文件头信息。
那么也就是说,如果有文件被offline后,我们无法单从dba_extents中知道该文件中包含有哪些segment。
那么我们应该再从dba_segments中得到segment header在该文件中的segment:
SQL> select distinct segment_name from dba_extents where file_id=10
2 union
3 select distinct segment_name from dba_segments where header_file=10;SEGMENT_NAME
——————————————————————————–
EAGLE_FAN
TEST
而DMT tablespace不存在这个问题,我们来看一看dba_extents的视图定义就很清楚了:
union all以上的部分对应于DMT tablespace,下面的部分对应于LMT tablespace。
DMT tablespace从uet$中读取extent信息,所以不受offline datafile的影响。
LMT tablespace从x$ktfbue中读取extent信息,对于x$ktfbue,描述为”Used extent bitmap in file header for LMT (equivalent to uet$ in DMT)”
我们来看看datafile offline前后,该表有什么变化:
– online datafile 10,多分配几个extent给表eagle_fan,并记录下一些信息
SQL> recover datafile 10
Media recovery complete.
SQL> alter database datafile 10 online;Database altered.
SQL> alter table eagle_fan allocate extent;
Table altered.
SQL> /
Table altered.
SQL> /
Table altered.
SQL> /
Table altered.
SQL> select extent_id,file_id,block_id from dba_extents where segment_name=’EAGLE_FAN’ order by extent_id;
EXTENT_ID FILE_ID BLOCK_ID
———- ———- ———-
0 10 7049
1 11 7177
2 10 7177
3 11 7305
4 10 7305SQL> select ktfbuefno file_id,count(*) from sys.x$ktfbue where ktfbuefno in (10,11) group by ktfbuefno;
FILE_ID COUNT(*)
———- ———-
10 58
11 58SQL> create table t as select * from sys.x$ktfbue where ktfbuefno in (10,11);
Table created.
– offline后再来比较,可以发现关于Eagle_Fan表的信息丢失
SQL> alter database datafile 10 offline;
Database altered.
SQL> select ktfbuefno file_id,count(*) from sys.x$ktfbue where ktfbuefno in (10,11) group by ktfbuefno;
FILE_ID COUNT(*)
———- ———-
11 56
10 55SQL> select e.ktfbuefno,e.ktfbuesegfno,e.ktfbuesegbno,e.ktfbuesegtsn from t e where ktfbuefno in (10,11) and
2 (ktfbuefno,ktfbuesegfno,ktfbuesegbno,ktfbuesegtsn)
3 not in (select ktfbuefno,ktfbuesegfno,ktfbuesegbno,ktfbuesegtsn from sys.x$ktfbue where ktfbuefno in (10,11))
4 ;KTFBUEFNO KTFBUESEGFNO KTFBUESEGBNO KTFBUESEGTSN
———- ———— ———— ————
10 10 7052 9
11 10 7052 9
10 10 7052 9
11 10 7052 9
10 10 7052 91* select header_file,header_block,segment_name from dba_segments where header_file=10 and header_block=7052
SQL> /HEADER_FILE HEADER_BLOCK SEGMENT_NAME
———– ———— ——————————
10 7052 EAGLE_FANSQL> select * from dba_extents where segment_name=’EAGLE_FAN’;
no rows selected
数据库的logfile被rm删除,每个logfile group仅有一个logfile member,当该logfile变为current时发现问题。
数据库仍然可以正常运行,但是LNS进程报错称找不到被删除的logfile。我们使用lgwr async模式传输redo到远端physical standby,physical standby无法得到被删除的logfile。
从pfiles中可以看出,因为lgwr进程每时每刻都获得所有logfile的文件句柄,所以虽然该logfile被删除,lgwr还是可以正常读写该logfile,数据库还是可以正常的运行。
但是lns进程只是获得当前的文件句柄,所以当切换到被删除的logfile时,lns进程不能访问该文件。
XFAN primary$> ps -ef |grep lns1|grep XFAN
oracle 17579 1 0 03:02:06 ? 0:01 ora_lns1_XFAN
XFAN primary$> pfiles 17579 | grep redo
/oracle/SCRATCH/data03/XFAN/redo/.redo2.log::cdev:vxfs: — LNS process only hold redo2.log’s handler
XFAN primary$> ps -ef |grep lgwr|grep XFAN
oracle 16377 1 0 02:44:54 ? 0:01 ora_lgwr_XFAN
XFAN primary$> pfiles 16377 |grep redo
/oracle/SCRATCH/data03/XFAN/redo/.redo1.log::cdev:vxfs:
/oracle/SCRATCH/data03/XFAN/redo/.redo2.log::cdev:vxfs:
/oracle/SCRATCH/data03/XFAN/redo/.redo3.log::cdev:vxfs:
/oracle/SCRATCH/data03/XFAN/redo/.redo4.log::cdev:vxfs: — LGWR process hold all redo log files’ handler
首先做的是在primary数据库上清除该logfile,过程如下:
1. 切换到好的logfile group
alter system switch logfile;
2. checkpoint,使该logfile的状态从active变为inactive
alter system checkpoint;
3. 清除该logfile,因为不能被归档,所以要加上unarchived
alter database clear unarchived logfile group x;
因为中间少了一个archive log,所以physical standby不能继续recover。
使用incremental backup来修复该physical standby,大约花费6个小时。如果重新build standby,大约需要花费一个星期。
在10.2版本logical standby环境中,如果primary上执行grant select on sequence to user,这条命令会复制到standby,如果sequence在standby上面不存在,apply process会停止工作。
对于有些部分复制的logical standby来说,需要忽略这部分错误。对于grant select on table to user,oracle已经很聪明的忽略了这类错误,显然grant sequence的问题是设计上的一个bug。
还好我们可以通过dbms_logstdby.skip_error来自动忽略此错误。
首先创建一个procedure用来处理GRANT的DDL 错误
CREATE OR REPLACE PROCEDURE sys.handle_error_ddl (
old_stmt IN VARCHAR2,
stmt_type IN VARCHAR2,
schema IN VARCHAR2,
name IN VARCHAR2,
xidusn IN NUMBER,
xidslt IN NUMBER,
xidsqn IN NUMBER,
error IN VARCHAR2,
new_stmt OUT VARCHAR2) AS
BEGIN
— Ignore any GRANT errors
new_stmt := old_stmt;
IF INSTR(UPPER(old_stmt),’GRANT’) > 0
THEN
new_stmt := NULL;
END IF;
END handle_error_ddl;
/
然后执行dbms_logstdby.skip_error,当遇到任何Non schema DDL的错误时,调用procedure sys.handle_error_ddl 来处理。
begin
DBMS_LOGSTDBY.SKIP_ERROR (‘NON_SCHEMA_DDL’, ”,”, ‘SYS.HANDLE_ERROR_DDL’);
end;
/
Oracle升级时间真的是越来越长,对于我们数百个数据库在限定的outage window内的升级,每一分钟都很珍贵。
之前我有一篇文章尽量缩短oracle upgrade时间讲述了一些缩短升级过程的技巧,不过对于10g到11g的升级,怎么算下来都需要1个多小时(目前我们还在寻找缩短11g升级时间的方法)。11g中含有set echo on的文件有下面6个,都是在$ORACLE_HOME/rdbms/admin下面:
1. catocm.sql
2. prvthtdb.plb
3. prvtaddm.plb
4. prvtpspi.plb
5. utlrdt.sql
6. prvtbog2.plb
这样的话,对于我们2个小时的outage window,如果升级过程中出现问题想做downgrade(downgrade过程大约需要40分钟),极大可能会超出outage window。所以必须找到一种快速downgrade的方法。这里便要提到10g的new feature — flashback database。
经过我的测试,flashback database只用了9秒钟,enable flashback会增加大约1分钟upgrade的时间。flashback area的实际使用大小大约为1.6GB。
具体步骤如下:
1. modify compatible = 10.2.0.4
2. Update log_archive_format = TEST_%s.%t_%r_arc
3. set diagnostic_dest in 11g init.ora
#diagnostic_dest=/oracle/TEST/data14/TEST #enabled when switching to 11g
4. Turn on Flashback
DB_RECOVERY_FILE_DEST_SIZE=4G
DB_RECOVERY_FILE_DEST=’/oracle/TEST/data14/TEST/flashback’– in 10g environment.
SQL> startup mount
SQL> alter database flashback on;
SQL> CREATE RESTORE POINT before_upgrade GUARANTEE FLASHBACK DATABASE;
Restore point created.
SQL> shtudown immediate;
– switching to 11g environmentSQL> startup upgrade
SQL> spool upgrade.log
SQL> set time on
SQL> @catupgrd.sqlSQL> startup
SYS@TEST:prod SQL> @?/rdbms/admin/utlu112s
.
Oracle Database 11.2 Post-Upgrade Status Tool 01-28-2010 00:49:30
.
Component Status Version HH:MM:SS
.
Oracle Server
. VALID 11.2.0.1.0 00:45:51
Oracle Real Application Clusters
. INVALID 11.2.0.1.0 00:00:02
Gathering Statistics
. 00:12:59
Total Upgrade Time: 00:58:55PL/SQL procedure successfully completed.
SQL> @?/rdbms/admin/catuppst
SQL> @?/rdbms/admin/utlrp
SQL> shutdown immediate– Flashback in 11g environment
SYS@TEST:prod SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SYS@TEST:prod SQL> startup mountSYS@TEST:prod SQL> set time on timing on
00:55:47 SYS@TEST:prod SQL> select FLASHBACK_ON from v$database;
FLASHBACK_ON
——————
RESTORE POINT ONLYElapsed: 00:00:00.01
00:55:54 SYS@TEST:prod SQL> FLASHBACK DATABASE TO RESTORE POINT before_upgrade;Flashback complete.
Elapsed: 00:00:09.00
Incomplete Recovery applied until change 3565405231814 time 01/27/2010 03:11:22
Flashback Media Recovery Complete
Completed: FLASHBACK DATABASE TO RESTORE POINT before_upgrade
SQL> shutdown immediate
– switch back to 10g versionSQL> startup mount
SQL> alter database open resetlogs;
Database altered.
SQL> select comp_name,version,status,modified from dba_registry;
SYS@USER10:prod SQL> select comp_name,version,status,modified from dba_registry;
COMP_NAME
————————————————————————————————————————————
VERSION STATUS MODIFIED
—————————— ——————————— ————————–
Oracle Database Catalog Views
10.2.0.4.0 VALID 01-MAY-2009 00:04:13Oracle Database Packages and Types
10.2.0.4.0 VALID 01-MAY-2009 00:04:13Oracle Real Application Clusters
10.2.0.4.0 INVALID 01-MAY-2009 00:04:13