1. checkpoint的本质

Checkpoint是Oracle数据库中的一种机制,用于将内存中的数据写入磁盘,以保证数据的持久性和一致性。Checkpoint的本质将数据库中的脏数据(即已经被修改但还没有写入磁盘的数据)写入磁盘同时更新数据库的控制文件和日志文件以便在数据库恢复时能够正确地恢复数据。

Checkpoint的实现方式通过Oracle后台进程LGWR(Log Writer)来完成的LGWR会定期将内存中的脏数据写入磁盘,并更新数据库的控制文件和日志文件。同时,它还会将写入磁盘的数据标记为干净数据(即已经被写入磁盘的数据),以便在数据库恢复时能够正确地恢复数据。

Checkpoint的频率和方式可以通过Oracle参数进行配置。一般来说,较小的Checkpoint间隔可以提高数据库的性能,但会增加磁盘I/O负载;较大的Checkpoint间隔可以减少磁盘I/O负载,但会降低数据库的性能。因此,在实际应用中,需要根据实际情况来配置Checkpoint的频率和方式,以保证数据库的性能和可用性。

当修改数据时,需要首先将数据读入内存中(Buffer Cache),同时,Oracle会记录Redo log用于恢复.因为有了Redo log的存在,Oracle不需要在提交时立即将变化的数据写回磁盘(立即写的效率会很低), Redo log的存在也正是为了在数据库崩溃之后, 可以恢复数据.

最常见的情况,数据库可以因为断电而Crash,那么内存中修改过的、尚未写入文件的数据将会丢失.在下一次数据库启动之后,Oracle可以通过重做日志(Redo)进行事务重演,也就是进行前滚,将数据库恢复到崩溃之前的状态,然后数据库可以打开继续使用,之后Oracle可以回滚未提交的数据.

在这个过程中,最重要的是数据库要经历多久才能打开.也就是需要读取多少重做日志才能完成前滚.这个时间越短越好.

检查点的存在就是为了缩短这个恢复时间.

当检查点发生时(此时的SCN被称为CheckPoint SCN),Oracle会通知DBWR进程,把修改过的数据,也就是Checkpoint SCN之前的脏数据(Dirty Data)从Buffer Cache写入磁盘,当写入完成之后,CKPT进程更新控制文件和数据文件头,记录检查点信息,标识变更.

在检查点完成之后,此检查点之前修改过的数据都已经写回磁盘,重做日志文件中的相应重做记录对于崩溃/实例恢复不再有用.

2. checkpoint主要作用

Checkpoint的主要作用保证数据库的持久性和一致性。具体来说,Checkpoint可以实现以下几个方面的作用

  1. 将内存中的脏数据写入磁盘Checkpoint可以将内存中的脏数据(即已经被修改但还没有写入磁盘的数据)写入磁盘,以保证数据的持久性和一致性。这样,在数据库发生故障或崩溃时,可以通过恢复日志将数据恢复到最近的Checkpoint时刻

  2. 更新数据库的控制文件和日志文件Checkpoint可以更新数据库的控制文件和日志文件,以便在数据库恢复时能够正确地恢复数据。控制文件包含了数据库的结构信息和状态信息,而日志文件则记录了数据库的所有修改操作,包括数据的插入、更新和删除等操作。

  3. 释放未使用的空间Checkpoint可以释放未使用的空间,以便将空间回收给操作系统。这样可以减少数据库的存储空间占用,同时也可以提高数据库的性能。

  4. 提高数据库的性能和可用性:Checkpoint可以减少数据库的I/O负载,从而提高数据库的性能和可用性。当数据库中存在大量的脏数据时,Checkpoint可以将这些数据写入磁盘,从而减少内存中的脏数据量,提高数据库的性能和可用性。

需要注意的是,Checkpoint的频率和方式可以通过Oracle参数进行配置。在实际应用中,需要根据实际情况来配置Checkpoint的频率和方式,以保证数据库的性能和可用性。同时,还需要定期监控Checkpoint的使用情况,以及进行Checkpoint的维护和优化。

3. checkpoint分类

 在Oracle数据库中,Checkpoint可以分为以下几种类型:

1.Complete Checkpoint完全Checkpoint是最常见的一种Checkpoint类型,它会将所有脏数据都写入磁盘,并更新数据库的控制文件和日志文件。完全Checkpoint会在以下情况下发生:

  • 执行ALTER SYSTEM CHECKPOINT命令时;
  • 数据库关闭时;
  • 数据库实例崩溃时。

2.Incremental Checkpoint增量Checkpoint是一种优化的Checkpoint类型,它只会将一部分脏数据写入磁盘,而不是全部写入。增量Checkpoint会在以下情况下发生:

  • 每隔一段时间(由参数FAST_START_MTTR_TARGET控制);
  • 当脏数据量达到一定阈值(由参数LOG_CHECKPOINT_INTERVAL控制);
  • 当数据库实例崩溃时。

3.Thread Checkpoint线程Checkpoint是一种特殊的Checkpoint类型,它只会将某个线程的脏数据写入磁盘,而不是全部线程的脏数据。线程Checkpoint会在以下情况下发生:

  • 当某个线程的脏数据量达到一定阈值(由参数LOG_CHECKPOINT_TIMEOUT控制);
  • 当数据库实例崩溃时。

需要注意的是,Checkpoint的类型和频率可以通过Oracle参数进行配置。在实际应用中,需要根据实际情况来选择最适合的Checkpoint类型和频率,以保证数据库的性能和可用性。同时,还需要定期监控Checkpoint的使用情况,以及进行Checkpoint的维护和优化。

4. 完全检查点

4.1 工作方式

记下当前的scn, 将此scn之前所有的脏块一次性写完,再将该scn号同步更新控制文件和数据文件头.

4.2 可以引起完全检查点的动作

a)正常关闭数据库 : shutdown immediate

b)手动切换检查点 : alter system checkpoint;

c)日志切换 : alter system switch logfile; --FAST_START_MTTR_TARGET 非0时,作用于增量检查点

d)数据库热备模式 : alter database begin backup;

4.3 验证

记下当前的SCN号(因为Oracle自身运行,scn会不停增长)
SQL> select current_scn from v$database;
CURRENT_SCN
-------------------
8609589
SQL> alter system checkpoint;
SQL> Select file#,checkpoint_change# from v$datafile;
-- 然后观察 v$datafile 和 v$datafile_header中scn被更新.
SQL> Select file#,checkpoint_change# from v$datafile_header;
 

[oracle@MaxwellDBA ~]$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Mon Apr 3 16:50:41 2023
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

sys@cdb$root:orclcdb> show user;
USER is "SYS"
sys@cdb$root:orclcdb> 
sys@cdb$root:orclcdb> select current_scn from v$database;

CURRENT_SCN
-----------
   31888378

1 row selected.

sys@cdb$root:orclcdb> alter system checkpoint;

System altered.

sys@cdb$root:orclcdb> Select file#,checkpoint_change# from v$datafile;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888385
         3           31888385
         4           31888385
         5            2153651
         6            2153651
         7           31888385
         8            2153651
         9           31888385
        10           31888385
        11           31888385
        12           31888385

11 rows selected.

sys@cdb$root:orclcdb> -- 然后观察 v$datafile 和 v$datafile_header中scn被更新.
sys@cdb$root:orclcdb> Select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888385
         3           31888385
         4           31888385
         5            2153651
         6            2153651
         7           31888385
         8            2153651
         9           31888385
        10           31888385
        11           31888385
        12           31888385

11 rows selected.

sys@cdb$root:orclcdb> 

5. 增量检查点及相关参数

5.1 概述

1).被修改过的块被统称为脏块.脏块按照首次变脏的时间顺序被一个双向链表指针串联起来,称做检查点队列(checkpoint queue).

2).当增量检查点发生时,DBWR就会被触发,沿着检查点队列的顺序将部分脏块刷新到磁盘上,每次刷新截止的那个块的位置就叫检查点位置,检查点位置之前的块,都是已经被DBWR刷新到磁盘上的块.而检查点位置对应的日志地址(RBA)又总是被记录在控制文件中(SCN号).如果发生系统崩溃,这个最后的检查点位置就是实例恢复的起点.

3).当增量检查点发生时,Oracle会写一部分脏块,使检查点位置前移.进而缩短实例恢复需要的日志起点和终点之间的距离,触发增量检查点越频繁,实例恢复的时间越少(脏块少了),但数据库性能受到频繁IO影响会降低.

4).增量检查点不会同步更新数据文件头和控制文件的SCN. 它只是根据策略计算一个SCN(未必是当前的SCN),将此SCN前的脏块刷新到磁盘,这个SCN点也叫检查点位置,然后将与此SCN有关的信息记录到控制文件中.(说明刷新一部分)

5.2 FAST_START_MTTR_TARGET参数

这个参数是NOTE.它定义多长时间恢复实例.(如何有效的缩短最近检查点位置与联机重做日志尾部之间的距离,正是设计此参数目的)

此参数单位为秒,缺省值0,范围0-3600秒,根据这个参数,Oracle计算出在内存中累积的 dirty buffer所需的日志恢复时间,如果到达该参数指定的时间,则增量检查点进程被触发.

该参数如果为0(增量检查点关掉),ORACLE则会根据DBWR进程自身需要尽量减少写入量,这样虽然实现了性能最大化,但实例恢复时间可能会比较长.

此参数并不是将脏块列表中所有脏块都写到数据文件中,而是一部分,保证满足条件即可.

早期还有几个有关增量检查点的参数,

log_checkpoint_interval

:规定了redo日志积累多少block后激活增量检查点*,对用户来讲要给出这个参数不太方便,所谓block指的是os block,*而不是oracle block.

log_checkpoint_timeout

:给一个触发增量检查点的间隔**,**单位是秒.

如果设置了FAST_START_MTTR_TARGET参数*,就不要用早期的一些参数,容易引起冲突.*

5.3 实验alter system switch logfile;

5.3.1 设置FAST_START_MTTR_TARGET

sys@cdb$root:orclcdb> 
sys@cdb$root:orclcdb> show parameter fast

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
fast_start_io_target                 integer     0
fast_start_mttr_target               integer     0
fast_start_parallel_rollback         string      LOW
sys@cdb$root:orclcdb> alter system set fast_start_mttr_target=900;

System altered.

sys@cdb$root:orclcdb> show parameter fast;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
fast_start_io_target                 integer     0
fast_start_mttr_target               integer     900
fast_start_parallel_rollback         string      LOW
sys@cdb$root:orclcdb>

5.3.2 查询v$log

sys@cdb$root:orclcdb> 
sys@cdb$root:orclcdb> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES  BLOCKSIZE    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME                    NEXT_CHANGE# NEXT_TIME                         CON_ID
---------- ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ----------------------------- ------------ ----------------------------- ----------
         1          1        478  209715200        512          1 NO  INACTIVE              31754474 02-APR-2023 10:05:28              31823564 02-APR-2023 22:43:38                   0
         2          1        479  209715200        512          1 NO  INACTIVE              31823564 02-APR-2023 22:43:38              31879508 03-APR-2023 14:00:27                   0
         3          1        480  209715200        512          1 NO  CURRENT               31879508 03-APR-2023 14:00:27            1.8447E+19                                        0

3 rows selected.

sys@cdb$root:orclcdb> 

5.3.3 查看数据文件和文件头

sys@cdb$root:orclcdb> 
sys@cdb$root:orclcdb> select file#,checkpoint_change# from v$datafile;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888385
         3           31888385
         4           31888385
         5            2153651
         6            2153651
         7           31888385
         8            2153651
         9           31888385
        10           31888385
        11           31888385
        12           31888385

11 rows selected.

sys@cdb$root:orclcdb> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888385
         3           31888385
         4           31888385
         5            2153651
         6            2153651
         7           31888385
         8            2153651
         9           31888385
        10           31888385
        11           31888385
        12           31888385

11 rows selected.

sys@cdb$root:orclcdb> 

5.3.4 日志切换

sys@cdb$root:orclcdb> 
sys@cdb$root:orclcdb> alter system switch logfile;

System altered.

sys@cdb$root:orclcdb> 

5.3.5 查询v$log和数据文件

sys@cdb$root:orclcdb> select file#,checkpoint_change# from v$datafile;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888385
         3           31888385
         4           31888385
         5            2153651
         6            2153651
         7           31888385
         8            2153651
         9           31888385
        10           31888385
        11           31888385
        12           31888385

11 rows selected.

sys@cdb$root:orclcdb> select file#,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888385
         3           31888385
         4           31888385
         5            2153651
         6            2153651
         7           31888385
         8            2153651
         9           31888385
        10           31888385
        11           31888385
        12           31888385

11 rows selected.

sys@cdb$root:orclcdb> 
-- 发现checkpoint_change#的值没有变化
-- 切换redo log file后,DBWR写脏块

5.3.6 几分钟后查询

v$log视图中的active状态几分钟后会变成inactive状态(及其对应的脏块写完),然后更新了控制文件和日志文件头部的SCN

sys@cdb$root:orclcdb> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES  BLOCKSIZE    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME                    NEXT_CHANGE# NEXT_TIME                         CON_ID
---------- ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ----------------------------- ------------ ----------------------------- ----------
         1          1        481  209715200        512          1 NO  CURRENT               31888563 03-APR-2023 16:57:30            1.8447E+19                                        0
         2          1        479  209715200        512          1 NO  INACTIVE              31823564 02-APR-2023 22:43:38              31879508 03-APR-2023 14:00:27                   0
         3          1        480  209715200        512          1 NO  INACTIVE              31879508 03-APR-2023 14:00:27              31888563 03-APR-2023 16:57:30                   0

3 rows selected.

sys@cdb$root:orclcdb> select file# ,checkpoint_change# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1           31888563
         3           31888563
         4           31888563
         5            2153651
         6            2153651
         7           31888563
         8            2153651
         9           31888563
        10           31888563
        11           31888563
        12           31888563

11 rows selected.

sys@cdb$root:orclcdb> 

5.4 NOTE

1).如果将 fast_start_mttr_target 设置为非 0

        a) 将启用检查点自动调整机制.

        b) log_checkpoint_interval参数将被覆盖掉.

2).90% OF SMALLEST REDO LOG(Oarcle 内部机制),将当前日志文件末尾还剩10%的位置设为检查点位置.

3).每3s查看checkpoint队列脏块的写出进度,注意,3s不触发检查点,它只是记录当时的检查点位置,并将相关信息写入到control file.

5.5 MTTR Advisory两个参数

实例恢复有关的顾问叫做MTTR Advisory需要设置两个参数

STATISTICS_LEVEL -->置为typical(缺省) 或者all //影响数据采集

FAST_START_MTTR_TARGET -->置为非零值

 5.6 设置合理的MTTR参数

sys@cdb$root:orclcdb> 
sys@cdb$root:orclcdb> -- 查看视图 v$instance_recovery
sys@cdb$root:orclcdb> select recovery_estimated_ios,actual_redo_blks,target_redo_blks,target_mttr,estimated_mttr from v$instance_recovery;

RECOVERY_ESTIMATED_IOS ACTUAL_REDO_BLKS TARGET_REDO_BLKS TARGET_MTTR ESTIMATED_MTTR
---------------------- ---------------- ---------------- ----------- --------------
                  1349            10064            24400          56             13

1 row selected.

sys@cdb$root:orclcdb> 

6. 局部检查点的触发条件

 对于某些操作,局部检查点是必须的,并会自动执行.

比如: tbs offline,datafile offline,删除extent, truncate表,begin backup(将 TBS置于备份模式)等.Oracle会根据需要自动执行.

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐