在 Oracle 的官方文档中介绍 Oracle 的 Checkpoint 有:
(1)Thread Checkpoint;
(2)Tablespace and datafile checkpoint;
(3)Incremental checkpoint。
对 于后两种 checkpoint,大家都有一个比较清晰的认识。 但是对于 Thread checkpoint 和 database checkpoint 之间的关系以及他们在单节点和RAC数据库之间的不同可能存在一些误区。 下面将通过一些例子来讲解一下 Thread checkpoint,以及在单节点和 RAC 中 Thread checkpoint 的不同。

一 单节点数据库(或者是RAC database中,只保留一个节点):

*为了便于观察checkpoint的,设置log_checkpoints_to_alert,让checkpoint的信息打印到alert log中:

SQL> show parameter log_checkpoints_to_alert

NAME                                 TYPE        VALUE
———————————— ———– ——————————
log_checkpoints_to_alert             boolean     TRUE


1) 对数据库做”alter system switch logfile”:


sys@R11203> select file#, CHECKPOINT_CHANGE# from v$datafile;

    FILE#         CHECKPOINT_CHANGE#
———- ————————–
        1             12717430780764
        2             12717430780764
        3             12717430780764
        4             12717430780764   <<<<<<<<<< 未switch之前

sys@R11203> alter system switch logfile;

System altered.

sys@R11203> select file#, CHECKPOINT_CHANGE# from v$datafile;

    FILE#         CHECKPOINT_CHANGE#
———- ————————–
        1             12717430780764
        2             12717430780764
        3             12717430780764
        4             12717430780764  <<<<<<<<<<<<< switch之后立即查看,v$datafile对应的checkpoint_change#并没有变化。


2)检查一下数据库的alert log:

Tue Jan 19 16:01:02 2016  
Beginning log switch checkpoint up to RBA [0x5a.2.10], SCN: 12717430780990    <<<<<<<<<<<<<<<  开始做log switch的checkpoint 到SCN12717430780990,但是并没有看到checkpoint结束。

3) 过了大约几分钟后,再次检查 alert log 以及 V$datafile

Tue Jan 19 16:05:58 2016   <<<<<<<<<<<<<<<<<< 16:05 已经结束checkpoint
Completed checkpoint up to RBA [0x5a.2.10], SCN: 12717430780990  


sys@R11203> select file#, CHECKPOINT_CHANGE# from v$datafile;

    FILE#         CHECKPOINT_CHANGE#
———- ————————–
        1             12717430780990
        2             12717430780990
        3             12717430780990
        4             12717430780990 <<<<<<<< v$datafile 中的checkpoint check# 已经更改到新的SCN:12717430780990

二 RAC数据库:

1) 对数据库做”alter system switch logfile”:

SQL> select INST_ID,INSTANCE_NAME,STATUS from gv$instance;

  INST_ID INSTANCE_NAME    STATUS
———- —————- ————
        1 ora11g1          OPEN
        2 ora11g2          OPEN

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337

6 rows selected.

SQL> alter system switch logfile;

System altered.

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337  <<<<<<<<<<  checkpoint_change# 并没有改变。

6 rows selected.

2) 观察此节点的alert log:

Wed Jan 20 07:10:16 2016
Beginning log switch checkpoint up to RBA [0x22f.2.10], SCN: 11583841 <<<<<<<<< 开始 log switch的checkpoint。
Thread 1 advanced to log sequence 559 (LGWR switch)
 Current log# 1 seq# 559 mem# 0: +DATA1/ora11g/onlinelog/group_1.257.827893181
Wed Jan 20 07:10:16 2016
Completed checkpoint up to RBA [0x22f.2.10], SCN: 11583841   <<<<<<<<<<  log switch的checkpoint已经完成。

3) 重新观察一下v$datafile:

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337  <<<<<<<<<<<< checkpoint_change# 还是没有改变。

6 rows selected.

4) 执行”alter system checkpoint”

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337

6 rows selected.

SQL> alter system checkpoint;

System altered.

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11583983
        2           11583983
        3           11583983
        4           11583983
        5           11583983
        6           11583983 <<<<<<<<<< 变成: 11583983

6 rows selected.

5) 观察此节点的alert log:

Wed Jan 20 07:14:21 2016
Beginning global checkpoint up to RBA [0x231.3.10], SCN: 11583983   <<<<<<<<<<  Global checkpoint到 11583983。
Completed checkpoint up to RBA [0x231.3.10], SCN: 11583983

6) 那么如果在RAC中做log switch,每次thread checkpoint的记录在哪里可以查询到呢?

SQL> select INSTANCE_NUMBER,INSTANCE_NAME,THREAD#,STATUS from gv$instance;

INSTANCE_NUMBER INSTANCE_NAME       THREAD# STATUS
————— —————- ———- ————
             1 ora11g1                   1 OPEN     <<<<<<<<<<<<<<<<<<<<   节点1的thead号为: 1
             2 ora11g2                   2 OPEN

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11616270
        2           11616270
        3           11616270
        4           11616270
        5           11616270
        6           11616270

6 rows selected.

SQL> alter system switch logfile;

System altered.

7)在alert log中:

Thu Jan 21 02:22:52 2016
Beginning log switch checkpoint up to RBA [0x23a.2.10], SCN: 11621392
Thread 1 advanced to log sequence 570 (LGWR switch)
 Current log# 2 seq# 570 mem# 0: +DATA1/ora11g/onlinelog/group_2.258.827893183
Thu Jan 21 02:22:53 2016
Archived Log entry 358 added for thread 1 sequence 569 ID 0xfbc6d574 dest 1:
Thu Jan 21 02:22:55 2016
Completed checkpoint up to RBA [0x23a.2.10], SCN: 11621392   <<<<<<<<<<<<<  Thread checkpoint 到 11621392已经完成。

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile;

    FILE# CHECKPOINT_CHANGE#
———- ——————
        1           11616270
        2           11616270
        3           11616270
        4           11616270
        5           11616270
        6           11616270 <<<<<<<<<< v$datafile中的checkpoint change#照例没有改变。

6 rows selected.

8) 查看v$thread:

SQL> select THREAD#,CHECKPOINT_CHANGE# from v$thread;

  THREAD# CHECKPOINT_CHANGE#
———- ——————
        1           11621392   <<<<<<<<<<<<<<<<  Thread 1 checkpoint 到 11621392 (和alert log中的描述一致)
        2           11619485

总结一下:

1. 对于单节点数据库,由于只有一个thread,所以由log switch发起的对当前thread的checkpoint,实质上就是整个数据库的checkpoint,所以log switch会导致v$datafile (v$datafile_header)中的checkpoint_change#改变。 但是必须要等checkpoint完成以后才会变成最新的值。
2. 对于RAC(2个节点以上)的数据库,由于至少存在2个或者以上的thread,所以对单一thread的 log switch并不会触发v$datafile (v$datafile_header)的checkpoint_change#的修改。原因是:只对其中一个thread(log)cover块的checkpoint,只会触发在此节点上脏块的写回. 但是由于多于2个节点,所以其他的节点可能存在在此checkpoint SCN之前的脏块,所以对于数据文件(或者是数据库)来说,这并不是一个完整的database级的checkpoint。 在RAC中,只有所有节点间的全局检查点(global checkpoint)会导致v$datafile中的checkpoint_change#的变化,比如”alter system checkpoint”。

 3. 在RAC中,对于thread的checkpoint_change#,可以通过v$thread来查询。