回顾前文:
什么是checksum?An optional checksum of the block contents. When a block is written, the checksum is eithercleared or set depending on the setting of the db_block_checksum parameter.When a block is read, the checksum is verified if present and if the parameteris set to TRUE. Checksums are always calculated and checked for blocks in theSYSTEM tablespace. (选自于http://www./notes/cache_header.htm ) 意思是说Checksum是一个可选项,当一个块被写入后,checksum或许会被设置或许会被清除,这个取决于db_block_checksum参数的设置。当读取一个块时,Checksum会被检验,如果db_block_checksum参数设置为true,并且这个块存在Checksum。SYSTEM表空间总是会被校验和检查无论db_block_checksum设置为True或False。 曾经有过的关于Checksum猜想?A.如果是对整个数据块做Checksum,然后写入数据块头部,如果是这样下次做Checksum和数据库头部原来Checksum值会不一致。
Checksum的正确算法The checksum is theXOR of all the other 2-byte pairs in the block. Thus when a block with achecksum is checked, the XOR of all the 2-byte words in the block should be 0. 以2个byte为一组,除offset16,17(从offset 0开始算起)外对块中所有内容做异或运算XOR(异或运算:如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0),然后把这个数值写入offset16,17(从offset 0开始算起)。这样整个块的异或计算之后的值就等于0。如果对数据块做更改,重新校验的值和原来offset(从offset 0开始算起)的值就不匹配。所以用BBED更改块后,必须重新计算和应用才能保证块的一致性。 大家也可以思考这样一个问题:假定Checksum(chkval_kcbh)占用2个字节,可不可以是3个byte一组,4个byte一组或者更多为一组呢? Checksum的标识KCBHFCKV几乎所有的块都有这个信息,占用20个字节,记录着块类型、版本、格式、RDBA、SCN和数据块的校验信息等信息。 type_kcbh:大部分块的类型是都是6(代表表、索引等类型的块)
其中KCBHFCKV是Checksum的标识,如果不设置,修改块时将不会计算新的Checksum值. 下面的测试时将flg_kcbh[0x06 (KCBHFDLC, KCBHFCKV)]修改为[0x02 (KCBHFDLC)]
随便做个更改,重新计算Checksum,Checksum值依旧保持不变
验证Checksum算法用dd复制数据块23,然后用oddump这个块内容。由于Linux为小端,需要将od输出内容做翻转,比如第一个a206,应该为06a2。也可以直接使用dd命令加conv=swab来以正常的格式来查看块内容。 可参考“如何在小端服务器以正常格式查看Oracle数据文件”http://www./index.php?m=Article&a=show&id=106查看 注意: -->这个后面是对应的XOR操作的结果,然后再将每行计算结果做XOR,最后计算出结果为2AFC。 如果感兴趣,自己可以动手算下。其实数据文件、控制文件、日志文件os块,也就是常说的block0,也有Checksum值。 大家也可以思考这样一个问题:假定Checksum(chkval_kcbh)占用2个字节,可不可以是3个byte一组,4个byte一组或者更多为一组呢? 请在留言中给出你的思考。 加入"云和恩墨大讲堂"微信群,参与讨论学习 |
|