日期:2014-05-16  浏览次数:20411 次

借助SCN的变化来理解oracle备份与恢复的基本原理

    SCN是oracle挂在墙上的时钟。早上起床,曰“起床SCN”;吃早餐,名“早餐SCN”;出门上班,称之为“出门SCN”。我们的任何活动,都会对应一个SCN。我们可借助oracle内部的一个包来获取系统的SCN(注意:这里只是系统的scn,因为,oracle还有commit scn,checkpoint scn,select scn等等)。

SQL> select dbms_flashback.get_system_change_number "system's scn" from dual;

system's scn
------------
      555956
    oracle内部只有一个SCN,其他的都是来自它。我们还可以看一下数据库里面最小的SCN。

SQL> select creation_change# "oracle内部最小scn" from v$datafile where file#=1;

oracle内部最小scn
-----------------
                9
    我们加在oracle身上的事,无论好坏,oracle都会依据SCN,一一记在心里(日志),莫敢相忘。由于SCN是递增的,我们对应到相关的SCN,就能找到那个时刻,我们对oracle所做的事。这便是SCN的重要性。
    我们对oracle所在的事,她会记在当前日志组。我们可以用v$log来查询。

SQL> select group#,sequence#,status from v$log;

    GROUP#  SEQUENCE# STATUS
---------- ---------- ----------------
         1          5 CURRENT
         2          3 INACTIVE
         3          4 INACTIVE
    接下来,我们对oracle做件事。我们建个表t,有两个字段。其中,字段scn可以约等于事务开始的scn。

  SQL> create table t(id int,scn number) tablespace users;

Table created.

SQL> insert into t values(1,dbms_flashback.get_system_change_number);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from t;

        ID        SCN
---------- ----------
         1     585887
    我们先把这件事缓缓,来看看v$log里面的first_change#。

SQL> alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';

Session altered.
SQL> select group#,status,first_change#,first_time from v$log;

    GROUP# STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------------- ------------- -------------------
         1 CURRENT                 583374 2012/07/17 19:59:23
         2 INACTIVE                560959 2012/07/17 17:13:32
         3 INACTIVE                560981 2012/07/17 17:14:33
    这里的first_change#和first_time是一样的,都是SCN的两种表现形式。first_change#是日志组成为当前日志组时所取的系统的SCN,来作为这一组最小或者开始的SCN。我们所做的事,对应的SCN,都会比first_change#来得大。
    继续我们的事,我们把当前日志组归档。

SQL> alter system switch logfile;

System altered.

    再瞧瞧v$log里面的first_change#

SQL> select group#,status,first_change#,first_time from v$log;

    GROUP# STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------------- ------------- -------------------
         1 ACTIVE                  583374 2012/07/17 19:59:23
         2 CURRENT                 586090 2012/07/18 09:35:40
         3 INACTIVE                560981 2012/07/17 17:14:33
    现在当前日志组变成了第2组,first_change#也发生了变化。
    再来继续我们未完的事。

SQL> insert into t values(2,dbms_flashback.get_system_change_number);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from t;

        ID        SCN
---------- ----------
         1     585887
         2     586129

    从这里我们可以看出,586129比当前日志组2的first_change#(586090)大。从而,证明了first_change#是当前日志组最小的SCN,之后,我们所做的任何事,产生的SCN,都会比这个来得大。
    我们再日志却,将日志组2归档。

SQL> alter system switch logfile;

System altered.

SQL> select group#,status,first_change#,first_time from v$log;

    GROUP# STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------------- ------------- -------------------
         1 ACTIVE                  583374 2012/07/17 19:59:23
         2 ACTIVE                  586090 2012/07/18 09:35:40
         3 CURRENT                 586181 2012/07/18 09:39:21

    现在,日志组3变成了当前日志组了,相应的first_change#也发生了变化。
    再来继续我们事情。为了产生更多的归档日志,我们不断的插入,提交,却换。