Archive

Author Archive

翠花

August 26th, 2010

周二陪老婆去看话剧《翠花》上海首演,主要还是看邓超。上戏剧院坐的满满的,女生居多,男生大部分是和我一样是陪客。

估计大部分都是邓超的粉丝。我对明星不感冒,不过看下来,邓超确实演得好,而且也没有因为自己大牌而偷懒,戏份很多。

这部戏如果没有邓超的表演只能算一般般。孙俪没现身,来的是孙俪她妈……

翠花海报

Eagle Fan Life

消失的segment

May 10th, 2010

这是在一次恢复演习中偶然发现的一个有趣的问题。

当LMT表空间中文件被offline后,如果该文件中包含有segment header,那么从dba_extents中不能看到该segment。

来看一个测试:

SQL> select file_id from dba_data_files where tablespace_name=’TEST’;

FILE_ID
———-
10
11

SQL> 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
———–
10

SQL> select extent_id ,file_id from dba_extents where segment_name=’EAGLE_FAN’ and owner=’SYS’;

EXTENT_ID FILE_ID
———- ———-
0 10

SQL> select distinct segment_name from dba_extents where file_id=10;

SEGMENT_NAME
——————————————————————————–
TEST
EAGLE_FAN

SQL> 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
——————————————————————————–
TEST

no 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的视图定义就很清楚了:

  1. select ds.owner, ds.segment_name, ds.partition_name, ds.segment_type,
  2.        ds.tablespace_name,
  3.        e.ext#, f.file#, e.block#, e.length * ds.blocksize, e.length, e.file#
  4. from sys.uet$ e, sys.sys_dba_segs ds, sys.file$ f
  5. where e.segfile# = ds.relative_fno
  6.   and e.segblock# = ds.header_block
  7.   and e.ts# = ds.tablespace_id
  8.   and e.ts# = f.ts#
  9.   and e.file# = f.relfile#
  10.   and bitand(NVL(ds.segment_flags,0), 1) = 0
  11.   and bitand(NVL(ds.segment_flags,0), 65536) = 0
  12. union all
  13. select
  14.        ds.owner, ds.segment_name, ds.partition_name, ds.segment_type,
  15.        ds.tablespace_name,
  16.        e.ktfbueextno, f.file#, e.ktfbuebno,
  17.        e.ktfbueblks * ds.blocksize, e.ktfbueblks, e.ktfbuefno
  18. from sys.sys_dba_segs ds, sys.x$ktfbue e, sys.file$ f
  19. where e.ktfbuesegfno = ds.relative_fno
  20.   and e.ktfbuesegbno = ds.header_block
  21.   and e.ktfbuesegtsn = ds.tablespace_id
  22.   and ds.tablespace_id = f.ts#
  23.   and e.ktfbuefno = f.relfile#
  24.   and bitand(NVL(ds.segment_flags, 0), 1) = 1
  25.   and bitand(NVL(ds.segment_flags,0), 65536) = 0

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 7305

SQL> select ktfbuefno file_id,count(*) from sys.x$ktfbue where ktfbuefno in (10,11) group by ktfbuefno;

FILE_ID COUNT(*)
———- ———-
10 58
11 58

SQL> 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 55

SQL> 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 9

1* 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_FAN

SQL> select * from dba_extents where segment_name=’EAGLE_FAN’;

no rows selected

Eagle Fan oracle

当logfile被删除后

April 1st, 2010

数据库的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,大约需要花费一个星期。

Eagle Fan oracle

Ignore sequence grant error on logical standby

February 26th, 2010

在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;
/

Eagle Fan oracle

Use flashback to downgrade oracle from 11g to 10g

February 21st, 2010

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 environment

SQL> startup upgrade

SQL> spool upgrade.log
SQL> set time on
SQL> @catupgrd.sql

SQL> 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:55

PL/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 mount

SYS@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 ONLY

Elapsed: 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 version

SQL> 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:13

Oracle Database Packages and Types
10.2.0.4.0 VALID 01-MAY-2009 00:04:13

Oracle Real Application Clusters
10.2.0.4.0 INVALID 01-MAY-2009 00:04:13

Eagle Fan oracle