作者介绍
梁铭图,新炬网络首席架构师,十多年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有Oracle OCM、Togaf企业架构师(鉴定级)、IBM CATE等认证,曾获dbaplus年度MVP以及华为云MVP等荣誉,并参与数据资产管理国家标准的编写工作。在数据库运维管理和架构设计、运维体系规划、数据资产管理方面有深入研究。
Oracle 的Online redo log 是为确保已经提交的事务不会丢失而建立的一个机制。因为这种健全的机制,才能让我们在数据库crash时,恢复数据,保证数据不丢失。一般而言,数据库随着数据库操作会不断将操作条目写入redo log,并且通过归档的方式备份操作日志加以备份。
日常运维中使用redo log的常用场景主要包括:
数据库crash后的恢复。
数据库从备份介质中的恢复。
数据实时同步工具(OGG、DSG)从中挖掘数据变化信息。
ADG向远端同步。
……
从手中的资料可查Oracle 日志文件的格式如下:
redo logfile的结构
block 0: file header
block 1: redo header
block 2: redo record 1
block 3: redo record 2
...
...
block N: redo record n
本文主要分析一下Redo log里面文件头里的信息。
一、准备工作
使用dbfsize(oracle自带工具)可以查看redo logfile信息。
SQL> col member for a40
SQL> select member from v$logfile;
MEMBER
----------------------------------------
/u01/app/oradata/test/redo03.log
/u01/app/oradata/test/redo02.log
/u01/app/oradata/test/redo01.log
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
$ dbfsize /u01/app/oradata/test/redo01.log
Database file: /u01/app/oradata/test/redo01.log
Database file type: file system
Database file size: 102400 512 byte blocks
<=====含义是redo块的大小是512字节,一共有102400个块
SQL> col member for a40
SQL> select a.member, b.bytes from v$logfile a, v$log b where a.group#=b.group#;
MEMBER BYTES
---------------------------------------- ----------
/u01/app/oradata/QXY/redo03.log 52428800
/u01/app/oradata/QXY/redo02.log 52428800
/u01/app/oradata/QXY/redo01.log 52428800
跟数据库查询的结果是一致的。
二、解读redo logfile的文件头
解析redo logfile header block(redo文件的第一个块):
$ dd if=/u01/app/oradata/test/redo01.log bs=512 count=1 | od -x
1+0 records in
1+0 records out
512 bytes (512 B) copied, 3.0992e-05 s, 16.5 MB/s
0000000 2200 0000 0000 ffc0 0000 0000 0000 0000 <======第一行
0000020 c867 0000 0200 0000 9000 0001 7c7d 7a7b 二
0000040 81a0 0000 0000 0000 0000 0000 0000 0000 三
0000060 0000 0000 0000 0000 0000 0000 0000 0000 四
*
0001000
其中可读取的信息为:
第一行的 2200 ----表示file type,0x22代表redo logfile
第二行的 0200 ----表示redo block 大小,转换成十进制为512
第二行的 9000 0001 -----大小端转换后是00019000,转换成十进制为102400
第二行的 7c7d 7a7b -----代表逻辑号
可以看到通过dd+od的方式读取的redo logfile的第一块的内容和dbfsize看到的数据一致,redo logfile 文件头主要描述该该文件是什么类型的文件,每个块大小是多少,一共有多少个块等。
解读redo logfile的redo header(第二个块):
$ dd if=/u01/app/oradata/test/redo01.log skip=1 bs=512 count=1 | od -x <=====skip=1,也就是跳过redo logfile的文件头块(第一个块)
1+0 records in
1+0 records out
512 bytes (512 B) copied, 3.5083e-05 s, 14.6 MB/s
0000000 2201 0000 0001 0000 0001 0000 8000 6f2c
0000020 0000 0000 0000 0b20 f07a fc4a 5851 0059
0000040 0000 0000 448a 0000 9000 0001 0200 0000
0000060 0001 0002 80c2 ff13 0000 0000 0000 0000
0000100 0000 0000 0000 0000 0000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 6854 6572
0000140 6461 3020 3030 2c31 5320 7165 2023 3030
0000160 3030 3030 3030 3130 202c 4353 204e 7830
0000200 3030 3030 3130 6637 3639 3331 302d 3078
0000220 3030 3030 3731 6666 3463 0063 4804 0000
0000240 ea1c 3ad1 9613 017f 0000 0000 0006 0000
0000260 0001 0000 9613 017f 0000 0000 ea1c 3ad1
0000300 fc4c 017f 0000 0000 4967 3ad3 0000 0208
0000320 9613 017f 0000 0000 ea1c 3ad1 fc4a 017f
0000340 0000 0000 28da 3ad2 0000 0000 0000 0080
0000360 0000 0000 0000 0000 0000 0000 0002 0000
0000400 0000 0000 0000 0000 0000 0000 0000 0000
0000420 0000 0000 0000 0000 0000 0000 9392 017f
0000440 0000 0000 e8f9 3ad1 0000 0000 0000 0000
0000460 0000 0000 0000 0000 0000 0000 0000 0000
*
0000700 5b73 a77c 06b1 482f 5802 3aaa a734 35fa
0000720 5e8c 05f2 25fe 9da5 996b 149e 5f26 1e03
0000740 0005 0000 0000 0000 0000 0000 0000 0000
0000760 0000 0000 0000 0000 0000 0000 0000 0000
0001000
offset 0~1 :2201 ----表示redo logfile block,redo block的第一个块都是这个值
offset 4~5 :0001 ----表示redo log block nuber号
offset 8~9 :0001 ----表示redo log sequence 号
offset 12~13:8000 ----表示offset值
上面部分内容结合在一起,就是redo的RBA信息。
RBA = logseq+log block number +offset = 0x000001.00000001.0008
offset 14~15: 6f2c ----表示checksum
offset 20~23:0000 0b20 ----表示db version , 对应redo dump里面的 Compatibility Vsn = 186646528=0xb200000
offset 24~27: f07a fc4a ----表示DB ID值,大小端转换后为fc4af07a,转换10进制为4232769658
offset 28~33: 5851 0059 0000 ----代表DB Name
offset 36~37 :448a ----表示control seq的值,转换成10进制为17546
offset 40~43 :9000 0001 ----表示file size,单位是redo block个数,转换成10进制为102400
offset 44~45 :0200 ----表示redo block size的大小,转换成10进制为512
offset 48~49 :0001 ----表示file number号,代表当前是redo的第一个文件
offset 50~51 :0002 ----表示file type的值,redo文件都是0002.
offset 52~55 :80c2 ff13 ---表示Activation ID的值,转换成10进制
offset 92~103:6854 6572 6461 3020 3030 2c31 -----代表"Thread 0001,"字符串
offset 104~121: 5320 7165 2023 3030 3030 3030 3030 3130 202c -----代表log seq号 "Seq# 0000000001,"
offset 122~153: 4353 204e 7830 3030 3030 3130 6637 3639 3331 302d 3078 3030 3030 3731 6666 3463 ----代表SCN的范围
offset 154~159: 0063 4804 0000 ---表示thread nab的值
offset 160~163:ea1c 3ad1 ---表示resetlogs count的值
offset 164~167:9613 017f ---表示resetlogs的scn值
offset 172~173: 0006 ---表示hws的值
offset 176~177:0001 ---表示eot的值
offset 180~183:9613 017f ---low scn的值
offset 188~191:ea1c 3ad1 ---表示resetlogs的值
offset 192~195:fc4c 017f ---next scn的值
offset 207~210:9613 017f ---Enabled scn的值
offset 219~222:fc4a 017f ---Thread closed scn的值
下面是redo dump的信息来进一步说明。
SQL> alter system dump logfile '/u01/app/oradata/test/redo01.log';
System altered.
<=====redo 文件头信息
DUMP OF REDO FROM FILE '/u01/app/oradata/test/redo01.log'
Opcodes *.*
RBAs: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff
SCNs: scn: 0x0000.00000000 thru scn: 0xffff.ffffffff
Times: creation thru eternity
FILE HEADER:
Compatibility Vsn = 186646528=0xb200000 <=====对应offset 20~23
Db ID=4232769658=0xfc4af07a, Db Name='QXY'<=====分别对应offset 24~33
FILE HEADER:
Compatibility Vsn = 186646528=0xb200000
Db ID=4232769658=0xfc4af07a, Db Name='test'
Activation ID=4279468226=0xff1380c2
Control Seq=17546=0x448a, File size=102400=0x19000 <======对应offset 36~43
File Number=1, Blksiz=512, File Type=2 LOG <======对应offset 44~51
descrip:"Thread 0001, Seq# 0000000001, SCN 0x0000017f9613-0x0000017ffc4c" <======对应offset 92~153
thread: 1 nab: 0x4804 seq: 0x00000001 hws: 0x6 eot: 0 dis: 0 <======对应offset 154~177
resetlogs count: 0x3ad1ea1c scn: 0x0000.017f9613 (25138707)
prev resetlogs count: 0x3ad1e8f9 scn: 0x0000.017f9392 (25138066)
Low scn: 0x0000.017f9613 (25138707) 09/14/2018 16:58:04 <===对应offset 180~183
Next scn: 0x0000.017ffc4c (25164876) 09/15/2018 17:56:55 <===对应offset 192~195
Enabled scn: 0x0000.017f9613 (25138707) 09/14/2018 16:58:04 <===对应offset 207~210
Thread closed scn: 0x0000.017ffc4a (25164874) 09/14/2018 21:25:46 <====对应offset219~222
Disk cksum: 0x6f2c Calc cksum: 0x6f2c
Terminal recovery stop scn: 0x0000.00000000
Terminal recovery 01/01/1988 00:00:00
Most recent redo scn: 0x0000.00000000
模拟redo header损坏。
替换之前DBID的值如下:
$ dd if=/u01/app/oradata/QXY/redo01.log skip=1 bs=512 count=1 | od -x
1+0 records in
1+0 records out
512 bytes (512 B) copied, 3.4274e-05 s, 14.9 MB/s
0000000 2201 0000 0001 0000 0001 0000 8000 6f79
0000020 0000 0000 0000 0b20 f07a fc4a 5851 0059 <=====f07a fc4a
0000040 0000 0000 44de 0000 9000 0001 0200 0000
0000060 0001 0002 80c2 ff13 0000 0000 0000 0000
0000100 0000 0000 0000 0000 0000 0000 0000 0000
用4个A执行替换:
[oracle@qxy QXY]$ echo AAAA |dd of=/u01/app/oradata/QXY/redo01.log seek=536 bs=1 count=4 conv=notrunc
4+0 records in
4+0 records out
4 bytes (4 B) copied, 4.9324e-05 s, 81.1 kB/s
其中seek=536代表跳过536个字节,其中536=512+24,其中512为第一个块redo file header 然后加上第二个块的偏移量24,正好为DBID所在的位置。
再次查询:
[oracle@qxy QXY]$ dd if=/u01/app/oradata/QXY/redo01.log skip=1 bs=512 count=1 | od -x
1+0 records in
1+0 records out
512 bytes (512 B) copied, 4.0794e-05 s, 12.6 MB/s
0000000 2201 0000 0001 0000 0001 0000 8000 6f79
0000020 0000 0000 0000 0b20 4141 4141 5851 0059 <====这里从原来的f07a fc4a 变成了4141 4141(即AAAA)
0000040 0000 0000 44de 0000 9000 0001 0200 0000
0000060 0001 0002 80c2 ff13 0000 0000 0000 0000
重新启动数据库,数据库报错如下:
SQL> startup
ORACLE instance started.
Total System Global Area 776646656 bytes
Fixed Size 2232392 bytes
Variable Size 603983800 bytes
Database Buffers 163577856 bytes
Redo Buffers 6852608 bytes
Database mounted.
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/QXY/redo01.log'
Alert日志错误如下:
starting up 1 shared server(s) ...
ORACLE_BASE from environment = /u01/app
Sat Sep 15 23:41:57 2018
ALTER DATABASE MOUNT
Successful mount of redo thread 1, with mount id 4279599365
Database mounted in Exclusive Mode
Lost write protection disabled
Completed: ALTER DATABASE MOUNT
Sat Sep 15 23:42:01 2018
ALTER DATABASE OPEN
Beginning crash recovery of 1 threads
parallel recovery started with 2 processes
Started redo scan
Errors in file /u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4176.trc:
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/QXY/redo01.log'
Aborting crash recovery due to error 366
Errors in file /u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4176.trc:
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/QXY/redo01.log'
Errors in file /u01/app/diag/rdbms/qxy/QXY/trace/QXY_ora_4176.trc:
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/QXY/redo01.log'
ORA-366 signalled during: ALTER DATABASE OPEN...
Sat Sep 15 23:42:01 2018
Errors in file /u01/app/diag/rdbms/qxy/QXY/trace/QXY_m000_4182.trc:
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/QXY/redo01.log'
Checker run found 2 new persistent data failures
查看trace的信息:
more /u01/app/diag/rdbms/qxy/test/trace/test_ora_4176.trc
Trace file /u01/app/diag/rdbms/test/test/trace/test_ora_4176.trc
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/11.2.0/dbhome_1
System name: Linux
Node name: test
Release: 2.6.32-431.el6.x86_64
Version: #1 SMP Sun Nov 10 22:19:54 EST 2013
Machine: x86_64
VM name: VMWare Version: 6
Instance name: test
Redo thread mounted by this instance: 1
Oracle process number: 19
Unix process pid: 4176, image: oracle@test (TNS V1-V3)
*** 2018-09-15 23:42:01.720
*** SESSION ID:(125.5) 2018-09-15 23:42:01.720
*** CLIENT ID:() 2018-09-15 23:42:01.720
*** SERVICE NAME:() 2018-09-15 23:42:01.720
*** MODULE NAME:(sqlplus@test (TNS V1-V3)) 2018-09-15 23:42:01.720
*** ACTION NAME:() 2018-09-15 23:42:01.720
Successfully allocated 2 recovery slaves
Using 67 overflow buffers per recovery slave
Thread 1 checkpoint: logseq 4, block 83, scn 25197573
on-disk rba: logseq 4, block 179, scn 25197821
start recovery at logseq 4, block 179, scn 25197821
DDE rules only execution for: ORA 312
----- START Event Driven Actions Dump ----
---- END Event Driven Actions Dump ----
----- START DDE Actions Dump -----
Executing SYNC actions
----- START DDE Action: 'DB_STRUCTURE_INTEGRITY_CHECK' (Async) -----
Successfully dispatched
----- END DDE Action: 'DB_STRUCTURE_INTEGRITY_CHECK' (SUCCESS, 1 csec) -----
Executing ASYNC actions
----- END DDE Actions Dump (total 1 csec) -----
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/test/redo01.log'
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/test/redo01.log'
ORA-00366: log 1 of thread 1, checksum error in the file header
ORA-00312: online log 1 thread 1: '/u01/app/oradata/test/redo01.log'
这说明Oracle数据库启动时检验数据库redo文件头时出错,导致数据库实例恢复不成功。
要让数据库启动起来,还需要使用dd重新修改redo01.log文件的DBID的值。
$ dd if=redo02.log skip=536 bs=1 count=4 of=/u01/app/oradata/test/redo01.log seek=536 bs=1 count=4 conv=notrunc
4+0 records in
4+0 records out
4 bytes (4 B) copied, 0.000988096 s, 4.0 kB/s
检查一下修改后的值如下:
$ dd if=/u01/app/oradata/QXY/redo01.log skip=1 bs=512 count=1 | od -x
1+0 records in
1+0 records out
512 bytes (512 B) copied, 6.2949e-05 s, 8.1 MB/s
0000000 2201 0000 0001 0000 0004 0000 8000 6403
0000020 0000 0000 0000 0b20 f07a fc4a 5851 0059 <=====由原来的41414141变为f07a fc4a
0000040 0000 0000 44f3 0000 9000 0001 0200 0000
0000060 0001 0002 80c2 ff13 0000 0000 0000 0000
0000100 0000 0000 0000 0000 0000 0000 0000 0000
重新启动数据库:
SQL> startup
ORACLE instance started.
Total System Global Area 776646656 bytes
Fixed Size 2232392 bytes
Variable Size 603983800 bytes
Database Buffers 163577856 bytes
Redo Buffers 6852608 bytes
Database mounted.
Database opened. <=====数据库正常启动
SQL>
三、小结
如果能够对redo header比较了解的话,就可以使用特殊手段来修复一些redo lheader损坏的情况,特别是当current的redo header出现问题,这个时候更有必要修复。如果认真对比redo01.log和redo02.log的redo header会发现两个文件的数据基本都是一致的,只有个别地方是每个redo file特有的。所以当一个redo logfile header损坏的情况下,可以参考他正常redo header的内容来修复损坏的redo header。
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721