通过数据库链指定AS OF SCN语句

一直不确定闪回查询的AS OF语句是否可以通过数据库链对远端数据库生效,而由于通过数据库链查询会使两个数据库的SCN同步,使得这个问题难以测试。
通过数据库链查询会导致源和目标库SCN同步:https://yangtingkun.net/?p=722
虽然Oracle会在通过数据库链执行查询或DML操作时同步数据库的SCN,但是指定的SCN是本地的还是远端的还是有意义的。
为了说明这种情况,创建一个JOB,定期进行数据的修改,以快速提高一个数据库的SCN:

SQL> SELECT dbid, name FROM v$database;
DBID NAME
---------- ---------
 452011237 ORAT2
SQL> SELECT COUNT(*) FROM t;
COUNT(*)
----------
731791
SQL> BEGIN
2 FOR i IN 1..100000 loop
3 INSERT INTO t VALUES (i, 'y');
4 commit;
5 END loop;
6 END;
7 /
PL/SQL PROCEDURE successfully completed.

在另一个数据库中将系统时间和SCN的对应关系保存:

SQL> SELECT dbid, name FROM v$database;
      DBID NAME
---------- ---------
1299676637 ORCL
SQL> CREATE DATABASE LINK TEST CONNECT TO TEST IDENTIFIED BY TEST USING '192.168.0.19:1524/orat2';   
DATABASE link created.
SQL> DECLARE
2 v_job NUMBER;
3 BEGIN
4 dbms_job.submit(v_job, 'begin insert into t_scn values (sysdate, dbms_flashback.get_system_change_number); end;', 
5 sysdate, 'sysdate + 1/86400');
6 commit;
7 END;
8 /
PL/SQL PROCEDURE successfully completed.

检查插入的SCN信息:

SQL> SELECT * FROM t_scn;
TIME                    SCN
------------------- -------
2012-04-06 18:38:39 5098024
2012-04-06 18:38:44 5098031
2012-04-06 18:38:49 5098035
2012-04-06 18:38:54 5098040
2012-04-06 18:38:59 5098045
.
.
.
2012-04-06 18:42:49 5098266
2012-04-06 18:42:54 5098271
2012-04-06 18:42:59 5098276
53 ROWS selected.
SQL> SELECT dbid, name, current_scn FROM v$database@test;
DBID NAME      CURRENT_SCN
---------- --------- -----------
 452011237 ORAT2         5173454
SQL> SELECT * FROM t_scn;
TIME                    SCN
------------------- -------
2012-04-06 18:38:39 5098024
2012-04-06 18:38:44 5098031
2012-04-06 18:38:49 5098035
2012-04-06 18:38:54 5098040
.
.
.
2012-04-06 18:43:04 5098280
2012-04-06 18:43:09 5098285
2012-04-06 18:43:14 5173457
56 ROWS selected.<pre>
可以看到,当前数据库由于执行了远端的查询,导致当前的数据库SCN和远端SCN同步。由于远端通过PL/SQL运行大量的事务,因此SCN涨幅很快,而当前数据库没有操作进行,基本上SCN以每秒1个的速度增加。在运行了查询后,SCN则直接增加了75000。
因此对于当前数据库的而言,SCN是不连续的,对于当前库而言,50982865173456之间的值没有任何区别,下面尝试通过SCN查询远端数据库中的记录:
<pre lang='SQL'>SQL> SELECT COUNT(*) FROM t@test AS OF scn 5098286;
COUNT(*)
----------
    731976
SQL> SELECT COUNT(*) FROM t@test AS OF scn 5173457;
COUNT(*)
----------
    804664
SQL> SELECT COUNT(*) FROM t@test AS OF scn 5100000;
COUNT(*)
----------
    733675
SQL> SELECT COUNT(*) FROM t@test AS OF scn 5140000;
COUNT(*)
----------
    772940

可以看到通过指定SCN可以查询到远端T表不同时刻的记录数,而这些指定的SCN是当前数据库跳过的SCN,因此可以确定,AS OF SCN语句指定的SCN是针对目标表所在数据库而言的。而Oracle可能正是出于类似的考虑,才会将远端数据库和本地数据库的SCN进行同步。

This entry was posted in ORACLE and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *