1.3 转储log buffer
oracle对很多内存结构都提供了转储到平面文件的功能,但是并没有直接提供转储日志缓冲区的功能。但是提供了转储日志文件的功能。我们前面已经知道,日志文件的内容就是日志缓冲区的完全拷贝,因此,转储日志文件就等于转储了日志缓冲区。
转储日志文件的命令为:
alter system dump logfile 'logfilename';
我们的实验过程如下。首先找到当前状态为CURRENT的日志文件是哪一个,以及它的全路径。
SQL> select group#,status from v$log;
GROUP# STATUS
---------- ----------------
1 INACTIVE
2 INACTIVE
3 CURRENT
SQL> select member from v$logfile where group#=3;
MEMBER
--------------------------------------------------------------------------------
/oracle/oradata/ora10g/redo03.log
然后,找到我们的redo_test表的object id,并进行更新操作。
SQL> desc redo_test
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME VARCHAR2(10)
SQL> select object_id from user_objects where object_name='REDO_TEST';
OBJECT_ID
----------
51367
SQL> select * from redo_test;
ID NAME
---------- ----------
1 abc
2 abc
SQL> update redo_test set name='cdf' where id=1;
SQL> commit;
最后,我们转储出当前使用的日志文件。
SQL> alter system dump logfile '/oracle/oradata/ora10g/redo03.log';
打开生成的跟踪文件,从中找到含有51367(表redo_test的object id)的所有相关记录,如下图所示。
图一
我们可以看到,第一行明确说明了,下面的内容都属于同一个重做记录(REDO RECORD)。
往下可以看到的CHANGE #的字样,这里的CHANGE #就表示改动向量(CHANGE VECTOR),我们可以看到一共生成了四个改动向量(第3、15、18、21行)。正像我们前面所描述的那样,第一个是对回滚段事务表的改动(CHANGE #2),第二个是对回滚段数据块的改动(CHANGE #4),第三个是对redo_test表的数据块的改动(CHANGE #1),第四个是提交时对回滚段事务表的改动(CHANGE #3)。注意,这里的CHANGE #后面的数值并不表示发生顺序,只不过是一个标识而已,发生的先后顺序要以SCN号为准,SCN号越小的表示越早发生。另外一个需要注意的是,在这个例子里,第四个提交时对回滚段事务表的改动(CHANGE #3)的改动向量并没有单独成为一个重做记录,这是因为我们发出update语句以后立即提交了。如果发出update语句以后,不立即提交,而是等待一段时间,然后再提交。这时转储出来的日志文件会显示出两个重做记录,最后的提交时对回滚段事务表的改动的改动向量会单独归到一个重做记录里去。后面会说明原因。
第8行的slot: 0表示被更新的记录位于数据块中的第一行。这与第35行的slot是一样的。如果我们发出“update redo_test set name='cdf' where id=2”时,就会发现这时slot为1。
第9行的size: 0表示修改后的值的长度减去修改前的值的长度的结果。而第36行的size表示修改前的值的长度减去修改后的值的长度的结果。由于我们这里修改前后的值的长度都是3,所以差额为0。如果我们发出“update redo_test set name='cdfg' where id=1”时,就会发现第9行的值为1,第36行的值为-1。
第11行的bdba表示redo_test表的数据块的地址,其实就是第3行的DBA所显示的地址。而hdba则表示redo_test表的segment header的地址。与第38行的值是相同的。第14行的col 1表示被更新的是表的第二列(第一列是col 0)。后面的[3]表示该列的值的长度,单位是字节。它们与第41行的内容是相同的。再后面的63 64 66则表示col 1列被更新后的值。我们来转换一下,如下所示。可以看到这正是我们更新后的“cdf”值。同样我们可以看到第41行的61 62 63,表示更新前的值,也就是“abc”。
SQL> select chr(to_number(63,'xx')),chr(to_number(64,'xx')),
2 chr(to_number(66,'xx')) from dual;
C C C
- - -
c d f
第15行的DBA: 0x00800009表示回滚段事务表的地址,这与第18行的DBA是一样的。由于回滚段事务表位于回滚段段头里,所以这也就是回滚段段头的地址。008表示文件号乘以4,00009表示数据块地址。我们转储出该段头来看看里面放了些什么。
SQL> select to_number('008','xxx')/4 file#,
2 to_number('00009','xxxxx') block# from dual;
FILE# BLOCK#
---------- ----------
2 9
SQL> alter system dump datafile 2 block 9;
我们打开所生成的跟踪文件,可以看到存放的正是回滚段事务表的信息。如下图二所示。我们可以看到粗体显示的正是我们发出的update语句在事务表中所登记的条目,state为9表示事务已经提交。
图二
第17行的uba: 0x0080085a.0075.13表示存放redo_test被更新前旧值的回滚段数据块所在的地址,这与第20行的uba是一样的。0080085a表示回滚段数据块所在的地址,0075表示顺序号,13表示在回滚映射中的最后一个条目。我们只需要关心0080085a即可,其组成部分和前面所介绍过的是一样的,008表示文件号乘以4,0085a表示回滚段数据块的地址。
SQL> select to_number('008','xxx')/4 as file#,
2 to_number('0085a','xxxxx') as block# from dual;
FILE# BLOCK#
---------- ----------
2 2138
SQL> alter system dump datafile 2 block 2138;
然后,打开生成的跟踪文件,找到含有51367(表redo_test的object id)的相关记录,如下图三所示。
图三
从上图中我们可以看到熟悉的bdba和hdba。以及最后一行的61 62 63,这就是更新前的旧值。同时我们还可以注意到KDO Op code: 21,这表示事务所进行的操作的类型代码。因为我是在10g环境下测试的,所以这里显示了代码21,就表示进行的是update操作。如果在10g以前,会显示URP字样。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9842/viewspace-414944/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/9842/viewspace-414944/