我们先回顾一下 Header 中的信息:
|
-- Header
buffer tsn: 11 rdba: 0x02c000e2 (11/226) scn: 0x0000.1bda33c7 seq: 0x01 flg: 0x02 tail: 0x33c70601 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data |
以及我们通过 Oracle 的包查看的该块的信息:
|
SQL> exec my_tool.show_rowid('AAAHaFAALAAAADiAAA');
Rowid Type..............................1
Object Number...........................30341
Relative Fno............................11
Block Number............................226
Row Number..............................0
PL/SQL 过程已成功完成。
SQL> |
tsn:
数据块所在的表空间的序号。而 my_tool.show_rowid 得到的 Relative Fno 是数据块所在的数据文件的相对序号,虽然都是 11,但意义不同,这里纯属巧合。
|
SQL> select ts# from v$tablespace where name = 'TP_TEST';
TS#
----------
11
SQL> select file_id from dba_data_files where tablespace_name='TP_TEST';
FILE_ID
----------
11 |
rdba:
该数据块在数据文件中的相对地址。这里同时显示了它的16进制信息和10进制信息。我们可以通过16进制数据来计算出来10进制信息:
|
SQL> select my_tool.GET_DBA_INFO('02c000e2') from dual;
MY_TOOL.GET_DBA_INFO('02C000E2')
-------------------------------------------------------
RFILE_NO=11 BLOCK_NO=226
SQL> |
scn:
该数据块的 SCN 号。我们可以把它转换成 10 进制的:
|
SQL> select to_number('1bda33c7', 'xxxxxxxxxxxxx') scn from dual;
SCN
----------
467284935 |
我们可以看一下系统此时的 SCN 号:
|
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
467894229 |
当 Oracle 读取该块时,会检查该块的 SCN,来决定是否构造一致性读。当发出查询时的 SCN 比数据块里的 SCN 值大,则直接读取该块;反之,则说明该块已经被其他事务更新,则会通过回滚段来构造一致性读取,返回发出查询的时间点时该数据块的状态。我们可以看一个小例子:
|
SQL> var rec_test3 refcursor
SQL> var n_scn number;
SQL> begin
2 open :rec_test3 for select * from test3;
3 select dbms_flashback.get_system_change_number into :n_scn from dual;
4 end;
5 /
PL/SQL 过程已成功完成。
SQL> update test3 set b = 111 where rownum = 1;
已更新 1 行。
SQL> select * from test3;
B
----------
111
666
666
666
666
666
已选择6行。
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
467919249
SQL> print :n_scn
N_SCN
----------
467919167
SQL> print :rec_test3
B
----------
666
666
666
666
666
666
已选择6行。 |
seq:
序列号。
tail:
保持一致性。tail = lower scn + type + seq = (1bda)33c7 + 06 + 01 = 33c70601
frmt:
Oracle8 以上为2。
chkval:
可选择的校验值。
check:
数据块的类型。
(参考冰冻奶茶的DATA BLOCK内部结构)