如果把oracle比作一个人,那么controlfile就好比是人的大脑。oracle中的大量运行机制都跟controlfile有种紧密关系,例如介质恢复,实例恢复,检查点等等。
对于linux和unix环境,当前数据处于run的时候,某个controlfile损坏是不影响数据库运行的,如下:
####破坏controlfile
[oracle@oracle-ogg oracleogg]$ echo "hellow" >> control01.ctl
[oracle@oracle-ogg oracleogg]$ cat /dev/null >>control01.ctl
####检查点,切换redolog
SQL> alter system switch logfile;
System altered.
SQL> /
System altered.
SQL> /
System altered.
SQL> /
System altered.
#### check alert log信息
Thread 1 advanced to log sequence 105 (LGWR switch)
Current log# 3 seq# 105 mem# 0: /home/oracle/app/oradata/oracleogg/redo03.log
Thread 1 advanced to log sequence 106 (LGWR switch)
Current log# 1 seq# 106 mem# 0: /home/oracle/app/oradata/oracleogg/redo01.log
Thread 1 advanced to log sequence 107 (LGWR switch)
Current log# 2 seq# 107 mem# 0: /home/oracle/app/oradata/oracleogg/redo02.log
Mon Sep 14 09:22:12 2015
Thread 1 advanced to log sequence 108 (LGWR switch)
Current log# 3 seq# 108 mem# 0: /home/oracle/app/oradata/oracleogg/redo03.log
Mon Sep 14 09:25:22 2015
这是为什么,那是因为其进程持有的句柄并没有释放,如下:
[oracle@oracle-ogg oracleogg]$ ps -ef|grep ckpt |grep -v grep
oracle 2126 1 0 09:14 ? 00:00:00 ora_ckpt_oracleogg
[oracle@oracle-ogg oracleogg]$ cd /proc/2126/fd
fd/ fdinfo/
[oracle@oracle-ogg oracleogg]$ cd /proc/2126/fd
[oracle@oracle-ogg fd]$ ls -ltr |grep control
lrwx------ 1 oracle dba 64 Sep 14 09:35 257 -> /home/oracle/app/oradata/oracleogg/control02.ctl
lrwx------ 1 oracle dba 64 Sep 14 09:35 256 -> /home/oracle/app/oradata/oracleogg/control01.ctl
############session 1 trace 跟踪
strace -fr -o /tmp/2126.log -p 2126
########session2 进行redo切换
#######观察trace log
2126 0.000000 getrusage(RUSAGE_SELF, {ru_utime={0, 214967}, ru_stime={0, 257960}, ...}) = 0
2126 0.000383 getrusage(RUSAGE_SELF, {ru_utime={0, 214967}, ru_stime={0, 257960}, ...}) = 0
2126 0.000113 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566511
2126 0.000057 semtimedop(163842, {{16, -1, 0}}, 1, {0, 670000000}) = -1 EAGAIN (Resource temporarily unavailable)
2126 0.670347 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000072 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000118 pwrite(256, "\25\302\0\0\3\0\0\0\0\0\0\0\0\0\1\4D\360\0\0\2\0\0\0\0\0\0\0\0\0\0\0"..., 16384, 49152) = 16384
2126 0.001369 pwrite(257, "\25\302\0\0\3\0\0\0\0\0\0\0\0\0\1\4D\360\0\0\2\0\0\0\0\0\0\0\0\0\0\0"..., 16384, 49152) = 16384
2126 0.001083 pread(256, "\25\302\0\0\1\0\0\0\0\0\0\0\0\0\1\4\317[\0\0\0\0\0\0\0\4 \v\314d\261\210"..., 16384, 16384) = 16384
2126 0.000082 pread(256, "\25\302\0\0\17\0\0\0\16\23\0\0\377\377\1\4\345\334\0\0\0@\0\0\0\0\0\0\0\0\0@"..., 16384, 245760) = 16384
2126 0.000063 pread(256, "\25\302\0\0\21\0\0\0\16\23\0\0\377\377\1\4\364\251\0\0\0\0\0\0\0\0\0\0\f\257\3144"..., 16384, 278528) = 16384
2126 0.000065 pread(256, "\25\302\0\0\31\1\0\0\347\22\0\0\377\377\1\4\7\376\0\0\27\0\7\0\337\7\0\0\0\0\0\0"..., 16384, 4603904) = 16384
2126 0.000927 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000049 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000034 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000033 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000175 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000053 semtimedop(163842, {{16, -1, 0}}, 1, {3, 0}) = -1 EAGAIN (Resource temporarily unavailable)
2126 3.001736 getrusage(RUSAGE_SELF, {ru_utime={0, 216967}, ru_stime={0, 257960}, ...}) = 0
2126 0.000089 getrusage(RUSAGE_SELF, {ru_utime={0, 216967}, ru_stime={0, 257960}, ...}) = 0
2126 0.000098 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566878
2126 0.000048 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566878
2126 0.000114 pread(256, "\25\302\0\0\1\0\0\0\0\0\0\0\0\0\1\4\317[\0\0\0\0\0\0\0\4 \v\314d\261\210"..., 16384, 16384) = 16384
@
"2126.log" [readonly][noeol] 337L, 39290C 8,1 Top
2126 0.000000 getrusage(RUSAGE_SELF, {ru_utime={0, 214967}, ru_stime={0, 257960}, ...}) = 0
2126 0.000383 getrusage(RUSAGE_SELF, {ru_utime={0, 214967}, ru_stime={0, 257960}, ...}) = 0
2126 0.000113 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566511
2126 0.000057 semtimedop(163842, {{16, -1, 0}}, 1, {0, 670000000}) = -1 EAGAIN (Resource temporarily unavailable)
2126 0.670347 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000072 times({tms_utime=21, tms_stime=25, tms_cutime=0, tms_cstime=0}) = 429566578
2126 0.000118 pwrite(256, "\25\302\0\0\3\0\0\0\0\0\0\0\0\0\1\4D\360\0\0\2\0\0\0\0\0\0\0\0\0\0\0"..., 16384, 49152) = 16384
2126 0.001369 pwrite(257, "\25\302\0\0\3\0\0\0\0\0\0\0\0\0\1\4D\360\0\0\2\0\0\0\0\0\0\0\0\0\0\0"..., 16384, 49152) = 16384
2126 0.001083 pread(256, "\25\302\0\0\1\0\0\0\0\0\0\0\0\0\1\4\317[\0\0\0\0\0\0\0\4 \v\314d\261\210"..., 16384, 16384) = 16384
2126 0.000082 pread(256, "\25\302\0\0\17\0\0\0\16\23\0\0\377\377\1\4\345\334\0\0\0@\0\0\0\0\0\0\0\0\0@"..., 16384, 245760) = 16384
2126 0.000063 pread(256, "\25\302\0\0\21\0\0\0\16\23\0\0\377\377\1\4\364\251\0\0\0\0\0\0\0\0\0\0\f\257\3144"..., 16384, 278528) = 16384
2126 0.000065 pread(256, "\25\302\0\0\31\1\0\0\347\22\0\0\377\377\1\4\7\376\0\0\27\0\7\0\337\7\0\0\0\0\0\0"..., 16384, 4603904) = 16384
其中我们观看
pwrite(256, "\25\302\0\0\3\0\0\0\0\0\0\0\0\0\1\4D\360\0\0\2\0\0\0\0\0\0\0\0\0\0\0"..., 16384, 49152) = 16384
256是fd里面的文件的描述符,16384表示块的大小,49152是offset
说明redo 切换时,ckpt需要些controlfile.
通过上面的进程跟踪,我们可以得到:
1.进程信息可以在/proc下看见,例如/proc/2126/stat
2.对于linux,对于文件的读写,是通过调用函数read,pwrite64来实现的。
3.我们可以发现检查点进程ckpt 3s触发一次的机制。
4.对于Pwrite64的操作,是通过fd(256,257)l两个文件来完成的,其中对应的offset都是49152,且我们知道这3个文件被写入的文件(我们知道是controlfile 的block大小16384)。
不管是完全检查点还是增量检查点,ckpt进程在操作controlfile之前,都需要先获得相关的latch,其实就是:checkpoint queue latch
SQL> select addr,latch#,name from v$latch where name like '%checkpoint%';
ADDR LATCH# NAME
---------------- ---------- ----------------------------------------------------------------
000000006001CD48 175 active checkpoint queue latch
000000006001CDE8 176 checkpoint queue latch
0000000060026288 216 gc checkpoint
000000006002A3F8 245 lock new checkpoint scn during media recovery
SQL> select latch#,child#,level#,name,addr from v$latch_children where name like '%checkpoint%';
LATCH# CHILD# LEVEL# NAME ADDR
---------- ---------- ---------- ---------------------------------------------------------------- ----------------
176 384 5 checkpoint queue latch 00000003790ED210
176 383 5 checkpoint queue latch 00000003790ED118
176 382 5 checkpoint queue latch 00000003790ECB10
176 381 5 checkpoint queue latch 00000003790ECA18
176 380 5 checkpoint queue latch 00000003790EC410
176 379 5 checkpoint queue latch 00000003790EC318
176 378 5 checkpoint queue latch 00000003790EBD10
176 377 5 checkpoint queue latch 00000003790EBC18
176 376 5 checkpoint queue latch 00000003790EB610
176 375 5 checkpoint queue latch 00000003790EB518
176 374 5 checkpoint queue latch 00000003790EAF10
手工持有latch:
SQL> !ps -ef|grep ckpt|grep -v grep
oracle 2126 1 0 09:14 ? 00:00:01 ora_ckpt_oracleogg
SQL> oradebug setospid 2126
Oracle pid: 12, Unix process pid: 2126, image: oracle@oracle-ogg (CKPT)
SQL> oradebug call kslgetl 1610730984 1
Function returned 1
kslgetl是一个函数 kernal service layer
select addr,latch#,name from v$latch where name like '%checkpoint%';
1610730984 由6001CDE8转换得来。
1表示 the level of the requested latch
------此时的alert log如下:
Errors in file /home/oracle/app/diag/rdbms/oracleogg/oracleogg/trace/oracleogg_ckpt_2126.trc (incident=38500):
ORA-00600: internal error code, arguments: [504], [0x08D990BF0], [32], [5], [channel operations parent latch], [5], [0], [0x06001CDE8], [], [], [], []
select addr,latch#,name from v$latch where name like '%parent latch%';
select latch#,child#,level#,name,addr from v$latch_children where latch#=51 and addr='0x08D990BF0'
3)涉及controlfile信息的视图以及基表
跟controlfile相关的视图主要有如下几个:
v$controlfile----------记录controlfile文件名,block size,以及block个数。
V$CONTROLFILE_RECORD_SECTION----记录controlfile record记录的组成部分(或存放什么内容)
v$BACKUP_CONTROLFILE_DETAILS---记录controlfile备份信息
V$BACKUP_CONTROLFILE_SUMMARY---controlfile备份的一个汇总信息
重要的两个基表的视图
select view_definition from v$fixed_view_definition where view_name='GV$CONTROLFILE';
select inst_id,decode(bitand(cfflg,1),0,'',1,'INVALID'),cfnam, decode(bitand(cffl2,1),0,'NO','YES'), cfbsz, cffsz from x$kcccf
select view_definition from v$fixed_view_definition where view_name='GV$CONTROLFILE_RECORD_SECTION';
select inst_id,decode(indx,0,'DATABASE',1, 'CKPT PROGRESS', 2, 'REDO THREAD',3,'REDO LOG',4,'DATAFILE',5,'FILENAME',6,'TABLESPACE',7,'TEMPORARY FILENAME',8,
'RMAN CONFIGURATION',9,'LOG HISTORY',10,'OFFLINE RANGE',11,'ARCHIVED LOG',12,'BACKUP SET',13,'BACKUP PIECE',14,'BACKUP DATAFILE',15, 'BACKUP REDOLOG',16,'DATAFILE COPY',17,
'BACKUP CORRUPTION',18,'COPY CORRUPTION',19,'DELETED OBJECT',20,'PROXY COPY',21,'BACKUP SPFILE',23,'DATABASE INCARNATION',24,'FLASHBACK LOG',25, 'RECOVERY DESTINATION', 26,
'INSTANCE SPACE RESERVATION', 27, 'REMOVABLE RECOVERY FILES', 28, 'RMAN STATUS', 29, 'THREAD INSTANCE NAME MAPPING', 30, 'MTTR', 31, 'DATAFILE HISTORY', 32, 'STANDBY DATABASE MATRIX', 33,
'GUARANTEED RESTORE POINT', 34, 'RESTORE POINT', 35, 'DATABASE BLOCK CORRUPTION', 36,
'ACM OPERATION', 37, 'FOREIGN ARCHIVED LOG', 'UNKNOWN'),rsrsz,rsnum,rsnus,rsiol,rsilw,rsrlw from x$kccrs where indx not in (22)
视图可以通过如下查询
select table_name from dict where table_name like '%FIX%';
SQL> desc x$kcccf;
Name Null? Type
----------------------------------------- -------- ----------------------------
ADDR RAW(8) ------位于sga中的地址
INDX NUMBER--------------controlfile记录的类型
INST_ID NUMBER------------实例编号
CFFLG NUMBER -----------表示状态
CFNAM VARCHAR2(513)--------文件名
CFFL2 NUMBER
CFBSZ NUMBER------------block size
CFFSZ NUMBER ---------block 总数
4)controlfile 相关的参数
_controlfile_block_size---控制文件block大小,10.2之前是8192,之后是16K,该参数不能更改,否则会出现ora-00218错误。
_controlfile_enqueue_holding_time------control file enqueue max holding time in seconds
_controlfile_enqueue_timeout---control file enqueue timeout in seconds 默认是900秒,超出时间阻塞进程就被kill掉。
_kill_controlfile_enqueue_blocker----enable killing controlfile enqueue blocker on timeout
_controlfile_update_check---该参数控制controlfile当前损坏后,是否进行检查,如果进行检查,那么发现某个controlfile不正常,那么数据库会crash. 默认值是off
control_file_record_keep_time---该参数表示空间文件中的所存记录保留的时间,默认是7天.主要是备份集copy,备份片,archivelog等信息。
[oracle@oracle-ogg oracleogg]$ cat /dev/null >control01.ctl
SQL> alter system set "_controlfile_update_check"=LOW;
System altered.
SQL> alter system checkpoint;
alter system checkpoint
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 5541
Session ID: 1 Serial number: 5
DDE: Problem Key 'ORA 227' was flood controlled (0x2) (incident: 40907)
ORA-00227: corrupt block detected in control file: (block 1, # blocks 1)
ORA-00202: control file: '/home/oracle/app/oradata/oracleogg/control01.ctl'
Action (ID=34340896) was flood controlled by a FC Qualifier
error 227 detected in background process
ORA-00227: corrupt block detected in control file: (block 1, # blocks 1)
ORA-00202: control file: '/home/oracle/app/oradata/oracleogg/control01.ctl'