暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 10g新的内建函数ora_rowscn

原创 eygle 2019-12-05
740

ORA_ROWSCN就是Oracle10g中引入的一个新的内建函数,这个函数可以用于返回相关行记录的SCN值。

我看通过数据看一下这个ORA_ROWSCN的用法

SQL> connect eygle/eygle
已连接。
SQL> create table test
  2  as select user_id,username,password,rpad(DEFAULT_TABLESPACE,2000,'*') tablespce
  3  from dba_users;
表已创建。

SQL> select username,ora_rowscn,dbms_rowid.rowid_block_number(rowid) blockno from test
  2  where rownum <8;
USERNAME                       ORA_ROWSCN    BLOCKNO
------------------------------ ---------- ----------
MGMT_VIEW                          465191        204
SYS                                465191        204
SYSTEM                             465191        204
DBSNMP                             465191        205
SYSMAN                             465191        205
EYGLE                              465191        205
PROXY                              465191        206

已选择7行。

可以注意到,通过ORA_ROWSCN可以得到每一行记录的SCN值,由于SCN通常在COMMIT时被增进,所以来测试一下数据变更时SCN的变更情况:

SQL> update test set username='DBA' where username='SYS';
已更新 1 行。

SQL> select username,ora_rowscn,dbms_rowid.rowid_block_number(rowid) blockno from test
  2  where rownum <8;
USERNAME                       ORA_ROWSCN    BLOCKNO
------------------------------ ---------- ----------
MGMT_VIEW                          465191        204
DBA                                465191        204
SYSTEM                             465191        204
DBSNMP                             465191        205
SYSMAN                             465191        205
EYGLE                              465191        205
PROXY                              465191        206

已选择7行。
SQL> commit;
提交完成。

SQL> select username,ora_rowscn,dbms_rowid.rowid_block_number(rowid) blockno from test
  2  where rownum <8;
USERNAME                       ORA_ROWSCN    BLOCKNO
------------------------------ ---------- ----------
MGMT_VIEW                          465340        204
DBA                                465340        204
SYSTEM                             465340        204
DBSNMP                             465191        205
SYSMAN                             465191        205
EYGLE                              465191        205
PROXY                              465191        206

已选择7行。

我们注意到,虽然只更新了一条记录,但是在BLOCK 204上的3条记录SCN都被增进了。这是因为在缺省条件下创建的数据表,ORA_ROWSCN所获得的SCN来自数据块头部,所以同一数据块上的记录的SCN会同时被增进,也只有一个SCN,可以转储一下相关的数据块简单了解一下:

SQL> select segment_name,file_id,block_id,blocks from dba_extents where segment_name='TEST';
SEGMENT_NAME            FILE_ID   BLOCK_ID     BLOCKS
-------------------- ---------- ---------- ----------
TEST                          4        201          8
SQL> alter system dump datafile 4 block 204;
系统已更改。

找到生成的trace文件:

SQL>@gettrcname
TRACE_FILE_NAME
-------------------------------------------------------------------------------
C:\ORACLE\ADMIN\EYGLE\UDUMP\eygle_ora_3364.trc

简要摘录跟踪文件:

Start dump data blocks tsn: 4 file#: 4 minblk 204 maxblk 204
buffer tsn: 4 rdba: 0x010000cc (4/204)
scn: 0x0000.000719bc seq: 0x02 flg: 0x06 tail: 0x19bc0602
frmt: 0x02 chkval: 0x63ae type: 0x06=trans data
……………………..
Block header dump:  0x010000cc
 Object id on Block? Y
 seg/obj: 0x38bf  csc: 0x00.71927  itc: 3  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x10000c9 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.00071927
0x02   0x0008.02c.000000d4  0x00800541.004e.05  --U-    1  fsc 0x0000.000719bc
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
 
data_block_dump,data header at 0x8da227c

这里数据块头的“SCN 0x0000.000719bc”就正是ORA_ROWSCN的来源:

SQL> select to_number('719bc','xxxxxx') from dual;
TO_NUMBER('719BC','XXXXXX')
---------------------------
                     465340

那么如果建表时启用了ROWDEPENDENCIES,那么情况就会完全不同。重新做一个测试,使用ROWDEPENDENCIES选项重新创建测试表:

SQL> drop table test;
表已删除。

SQL> CREATE TABLE TEST ROWDEPENDENCIES
  2  AS SELECT user_id,username,PASSWORD,RPAD(default_tablespace,2000,'*') tablespce
  3  FROM dba_users;
表已创建。

SQL> SELECT username, ora_rowscn, DBMS_ROWID.rowid_block_number (ROWID) blockno
  2    FROM TEST
  3   WHERE ROWNUM < 7;
USERNAME                       ORA_ROWSCN    BLOCKNO
------------------------------ ---------- ----------
MGMT_VIEW                          466578        212
SYS                                466578        212
SYSTEM                             466578        212
DBSNMP                             466578        213
SYSMAN                             466578        213
EYGLE                              466578        213

已选择6行。

更新数据再来查看ROWSCN的变化:

SQL> update test set username='DBA' where username='SYS';
已更新 1 行。

SQL> commit;
提交完成。

SQL> SELECT username, ora_rowscn, DBMS_ROWID.rowid_block_number (ROWID) blockno
  2    FROM TEST
  3   WHERE ROWNUM < 7;
USERNAME                       ORA_ROWSCN    BLOCKNO
------------------------------ ---------- ----------
MGMT_VIEW                          466578        212
DBA                                466635        212
SYSTEM                             466578        212
DBSNMP                             466578        213
SYSMAN                             466578        213
EYGLE                              466578        213

已选择6行。

注意到此时仅有被更新记录的ROWSCN发生了变化,这是如何实现的呢?通过转储block就可以很容易地发现Oracle的这个秘密:

Block header dump:  0x010000d4
 Object id on Block? Y
 seg/obj: 0x38c0  csc: 0x00.71e92  itc: 3  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x10000d1 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.00071e92
0x02   0x0006.01c.000000d3  0x0080178a.0043.33  --U-    1  fsc 0x0000.00071ecb
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
 
data_block_dump,data header at 0x8da227c
……
tab 0, row 0, @0x1786
tl: 2042 fb: --H-FL-- lb: 0x0  cc: 4
dscn 0x0000.00071e92
……
tab 0, row 1, @0xf93
tl: 2035 fb: --H-FL-- lb: 0x2  cc: 4
dscn 0x0000.00071e92
……
tab 0, row 2, @0x79c
tl: 2039 fb: --H-FL-- lb: 0x0  cc: 4
dscn 0x0000.00071e92
……

此时,每条记录种都包含了额外的信息,即DSCN,这就是每条记录的SCN,由于Oracle采用延时写出,当前记录的SCN未被更新,ORA_ROWSCN查询的SCN信息来自ITL中的Scn/Fsc信息。

SQL> select to_number('71ecb','xxxxxx') from dual;
TO_NUMBER('71ECB','XXXXXX')
---------------------------
                     466635
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论