一直不确定闪回查询的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是不连续的,对于当前库而言,5098286和5173456之间的值没有任何区别,下面尝试通过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进行同步。