深入分析:12C ASM Normal冗余中PDB文件块号与AU关系与恢复(二)
刚才说到 ASMTABLE 这个表是由 21 号文件的,128,129,130,131,132,133,134,135,注意这里不连续,160,161,162,163,164,165,166,167,这16个块构成。
以下是罗列的一些知识点:
数据文件上的块号也是连续的。
到这里就能把表的块号跟实际磁盘和AU对应起来了。
例如,假如说5号文件的17520块是哪个磁盘的哪个AU:
(17520*block_size)/au_size,就能得到extent_number号,根据分布图,找这个extent_number对应的AU和磁盘即可。
--但是注意:11.1以后,出现了可变extent,就是说在extent较大的时候,一个extent里有多个AU,具体数值应该是1M的AU size的时候,数据文件超过20G会触发可变extent。
附加验证:
用 dd 的方法,把一个表 dd 出来,然后,把这个表 delete 掉,然后再拿 dd 出来的块,覆盖回去,看看数据还在不在。
前面说过,数据库是 8192 的,AU 是 4M,所以一个 AU 可以存放,4*1024/8=512个块。 也就是说,这个表的所有块都在第一个 AU 里。
就是前面的这个 AU:
FILE_NAME FILE_NUMBER DISK_NUMBER AU_NUMBER EXTENT_NUMBER P/S_EXTENT GROUP_NUMBER PATH AU_SIEZ_MB NAME
ASMRES.271.978291939 271 4 321 0 0 1 /dev/mapper/data07 4 DATAC1
在 /dev/mapper/data07 盘上的 .AU 号是 321。
下面我们从数据文件上的位置,dd 出来这个表的数据。然后 SQLPLUS 清空这个表,再把 dd 出来的表块放回去。以验证我们推测的分布是正确的。
注意知识点:
ASM 文件跟放在文件系统上的数据文件,头部不一样,ASM 上的文件头部会多出来一个块。
比如创建一个 10M 的数据文件,在文件系统上是 10240K,在 ASM 上,这个文件的size 是10240+8K。
下面从已经 dd 出来的数据文件上,把表的 16 个块都 dd 出来。
dd if=asmres.all.dbf of=8_block_1.dd skip=129 bs=8192 count=8
dd if=asmres.all.dbf of=8_block_2.dd skip=161 bs=8192 count=8
SQL> select BYTES/1024 from dba_segments where segment_name='ASMTABLE';
BYTES/1024
---------------
128
把这个表,delete,清空掉。(如果这里用 truncate 会影响后面的结果不?)
SQL> delete from asmtable;
511 rows deleted.
SQL> commit;
Commit complete.
SQL> select count(*) from asmtable;
COUNT(*)
---------------
0
然后把刚才 dd 出来的文件覆盖回去。覆盖 /dev/mapper/data07 这个盘的 321 号AU,为了方便,我们把这个 AU 拿出来。
dd if=/dev/mapper/data07 bs=4194304 count=1 skip=321 of=AU_321_0.dbf
把上面提取出来的表的两个 dd 写进这个 AU 的 dd,再把这个 AU 的 dd 写回磁盘。
dd if=asmres.all.dbf of=8_block_1.dd skip=129 bs=8192 count=8
dd if=asmres.all.dbf of=8_block_2.dd skip=161 bs=8192 count=8
dd if=8_block_1.dd of=AU_321_0.dbf seek=129 bs=8192 count=8 conv=notrunc
dd if=8_block_2.dd of=AU_321_0.dbf seek=161 bs=8192 count=8 conv=notrunc
dd if=AU_321_0.dbf bs=4194304 count=1 seek=321 of=/dev/mapper/data07 conv=notrunc
然后重启整个数据库。
SQL> alter session set container=ora122pdb1;
Session altered.
SQL> select count(*) from asmtable;
COUNT(*)
----------
511
验证完毕,这样方式对应的 block 号和 au 号是正确的。