23.控制文件和scn
1.前言
在oracle中有这样的一个比喻:控制文件是数据库的大脑,而system表空间是数据库的心脏,这里我们在回顾一下数据库启动过程,首先是nomount阶段,在该阶段,oracle首先寻找参数文件,然后根据参数文件的参数(如内存分配大小等),创建实例(instance),分配内存,启动后台进程,也就是nomount阶段就是启动数据库实例的过程。当后台进程启动后,然后数据库就进入了第二阶段,mount阶段,数据库根据参数文件获取控制文件的信息,然后找到控制文件,并且根据控制文件中记录的数据文件位置进行数据文件的存在判断。由于控制文件中记录了数据库中的数据文件,日志文件的位置信息,检查点等信息,在数据库open节点,oracle会根据这些信找到文件并进行检查点以及完整性检查,如果不存在问题就可以正常启动数据库,如果存在不一致或丢失则需要进行恢复。
简言之,oracle数据库启动的过程就是 由参数文件中记录的信息找到控制文件位置--->再由控制文件内记录的信息去找数据文件和日志文件位置并最终进行检查点和完整性检查。
2.控制文件中到底记录有哪些信息呢?
-
数据库名称以及数据库创建时间等
- 所有数据文件和重做日志文件的名称和位置信息等;
- 表空间信息
- OFFLINE数据文件信息;
- 重做日志以及归档日志信息;
- 备份集和备份文件信息;
- 检查点(checkpoint)以及scn信息等;
由于控制文件是二进制文件,因此用普通方式是不能打开的,但是我们可以使用以下命令可以将控制文件内容给转储出来进行查看:
SQL> alter session set events 'immediate trace name controlf level 8'; Session altered. SQL> select value from v$diag_info where name='Default Trace File'; VALUE -------------------------------------------------------------------------------- /data/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_16942.trc
打开这个追踪文件就可以清晰地看到控制文件内容,在这个文件中多次提到checkpoint和scn信息,在oracle数据库内部主要是通过scn和检查点来保证数据的一致性、可恢复性等重要功能。
3.什么是scn?
scn全称system change number,又称system commit number,但大多情况下叫system change number比较多。它在数据库内部通常叫做系统改变号,是数据库中非常重要的一个数据结构,用以标识数据库在某个确切时刻提交的版本。在事务提交时,它被赋予一个唯一的标识事务的scn。
scn在数据库中是无处不在的,常见的事务表,控制文件,数据文件,日志文件,数据块头等都记录了scn的值,因此也被冠不同的前缀, 比如说checkpint scn,resetlog scn等
如果获取scn,这里有几种方法,但是这里我常用的是:
SQL> select current_scn from v$database; CURRENT_SCN ----------- 2829533
4.SCN进一步说明
系统当前scn并不是在任何的数据库操作发生时都会改变,scn通常在事务提交或回滚时改变,在控制文件、数据文件、数据块、日志文件头、日志文件change vector中都有scn,但其作用不同
(1)数据文件头中包含了该数据文件的checkpoint scn,表示该数据文件最近一次执行检查点操作时的scn,对于每一个数据文件都包含一个这样的条目,记录该文件的检查点scn的值以及检查点的时间,在数据库启动的过程中,有一个一致性的检查的工作,其目录就是对比控制文件中记录的scn和数据文件头中记录的scn是否一致来判断是否进行恢复。
5.检查点(checkpoint)
检查点只是一个数据库事件,它存在的根本意义在于减少崩溃恢复(crash recovery)时间,检查点事件有ckpt后台进程触发,当检查点发生时,ckpt进程会负责通过dbwr进程将脏数据写到数据文件上,ckpt进程的另外一个职责是负责更新数据文件头以及控制文件上的检查信息。
检查点的工作原理:
在oracle数据库中,当进行数据修改时,需要首先将数据读入内存中,修改数据的同时,oracle会记录重做信息用于恢复,因为有了重做信息,oracle不需要在事务提交时立即将变化的数据写入磁盘(立即写的效率会很低),重做的存在也正是为了在数据库崩溃之后,数据可以恢复。
最常见的情况,数据库可能因为断电而crash,那么内存中修改的,尚未写入数据文件的数据将会丢失。在下一次数据库启动之后,oracle可以通过重做日志进行事务重演(前滚),将数据库恢复到崩溃之前的状态,然后数据库可以打开提供使用,之后oracle可以将未提交的事务进行回滚。
在这个启动过程中,通常需要关心的是大概需要多久才能打开数据库,这时我们的检查点就是为了缩短这个恢复时间而存在的,当检查点发生时(此时的scn被为了checkpoint scn)会通知dbwr进程,把修改过的数据,也就是checkpint scn之前的脏数据从buffer cache中写入磁盘,当写入完成之后,ckpt进程则会更新控制文件和数据文件投,记录检查点信息,标识变更。
查看checkpoint scn可以从数据库中进行查询
SQL> select dbid,checkpoint_change# from v$database; DBID CHECKPOINT_CHANGE# ---------- ------------------ 1611227666 2830183
在检查点完成之后,此检查点之前修改过的数据都已经写到了磁盘,重做日志文件中相应的记录对于崩溃/恢复不再有用。alte
一次checkpoint动作会触发如下行为:
- 把redo buffers的内容刷到redo log中。
- 在redo log file中留下一个checkpoint记录
- 把database buffer cache的变更刷新到磁盘。
- 在checkpoint完成后,更新数据文件头和控制文件。
触发条件
- 当发生日志组发生切换时:alter system swtich logfile;
- database buffer cache到达指定的块时
- 达到checkpoint指定的时间时,( LOG_CHECKPOINT_TIMEOUT,LOG_CHECKPOINT_INTERVAL,fast_start_io_target,fast_start_mttr_target 参数设置的时候)
- 当手工执行allter system checkpoint;
- 当执行alter tablespace xxx begin backup; end backup;
- alter tablespace,datafile offline时
5.SCN进行一步说明
4中SCN:
- 系统检查点(System Checkpoint) SCN
- 数据文件检查点(Datafile Checkpoint) SCN
- 结束SCN(Stop SCN)
- 开始SCN(Start SCN)
1)system checkpoint scn
-- 当checkpoing完成后,oracle将system Checkpoint Scn号存放在控制文件中,可以通过sql语句查询:
-- select checkpoint_change# from v$database;
2) datafile checkpoint scn
--当checkpoint完成后,Oracle将datafile checkpoint scn存放在控制文件中。可以通过下面的sql语句查询所有数据数据文件的datafile checkpoint SCN.
-- select name,checkpoint_change# from v$datafile;
3) Start scn
-- Oracle将start scn存放数据文件中。这个scn用于检查数据库启动过程是否需要做media recovery。可以通过如下sql语句查询
-- select name,checkpoint_change# from v$datafile_header;
4) Stop scn
-- Oracle将stop scn存放在控制文件中。这个scn号用于检查数据库启动过程是否需要做instance recovery,可以通过sql语句查询
-- select name,last_change# from v$datafile;
-- 在数据库正常运行的情况下,对可读写的online数据文件,该scn号为Null
SCN与数据库启动:
在数据库启动过程中,当System Checkpoint SCN、Datafile Checkpoint SCN和Start SCN都相同时,数据库可以正常启动,不需要做media recovery。三者当中有一个不同时,则需要做media recovery.如果在启动的过程中,End SCN为NULL,则需要做instance recovery。Oracle在启动过程中首先检查是否需要media recovery,然后再检查是否需要instance recovery。
SCN与数据库关闭:
如果数据库的正常关闭的话,将会触发一个checkpoint,同时将数据文件的END SCN设置为相应数据文件的Start SCN。当数据库启动时,发现它们是一致的,则不需要做instance recovery。在数据库正常启动后,ORACLE会将END SCN设置为NULL.如果数据库异常关闭的话,则END SCN将为NULL。
oracle在控制文件中记录system checkpoint scn号的同时,为什么还要为每个数据文件记录datafilecheckpoint scn?
- 如果有表空间read only,那么该表空间的所有datafile的start scn和stop scn将被冻结,这个时候就跟system checkpoint scn不一致,但是在库open的时候不需要做media recovery的,如果没有datafileCheckpoint scn就无法判断这些datafile是否是最新的。
参考:https://zhuanlan.zhihu.com/p/31446957/