#第三章 SCN(system change numbe)
3.1 Oracle SCN 概念
SCN(system change number): 系统改变号,用以标识数据库在某个确切的时刻提交的版本。
- 在事务提交时,它被赋予一个唯一的标示事务的SCN。
- 是Oracle内部的时钟机制;
- 通过SCN来维护数据库的一致性;
- 通过SCN来实施恢复机制;
- SCN在数据库中是唯一的,并随时间而增加,但是可能并不连贯。
- 系统检查点SCN: 查询目前系统最新的SCN(redo log SCN)
123456 col GET_SYSTEM_CHANGE_NUMBER for 99999999999999;select dbms_flashback.get_system_change_number from dual;GET_SYSTEM_CHANGE_NUMBER------------------------11795798036771
这里返回的SCN,是目前redo log file最新的SCN纪录。因为commit后的交易才会有SCN,而一旦commit就会立刻写入redo log file中。
CHECKPOINT和SCN的关联
Checkpoint发生的目的就是要把存储在buffer内的已提交交易写回disk,否则一旦发生crash,需要进行recovery时,就必须花很多时间从redo log file内最后的SCN交易开始进行recovery,这样在商业应用上是很浪费时间和没有效率的。
当commit一笔交易时,只会立刻将redo buffer写入redo log file内,但是并不会马上将该update后的block(dirty block)同步写回disk datafile中,这是为了减少过多disk IO,所以采取batch方式写入。
When a checkpoint occurs. Oracle must update the headers of all datafiles to record the details of the checkpoint. This is done by the CKPT process. The CKPT process does not write blocks to disk; DBWn always performs that work.
SCN写入的地方
在shutdown normal or shutdown immediate下, checkpoint也会自动触发。当发生checkpoint时,会把SCN写到四个地方去。三个地方在control file 内,一个在datafile header。
Control file三个地方为:
1. System checkpoint SCN
123456 col checkpoint_change# for 99999999999999;select checkpoint_change# from v$database;CHECKPOINT_CHANGE#------------------117957980230822. Datafile checkpoint SCN
123456 select name, checkpoint_change# from v$datafile where name like '%user%';NAME CHECKPOINT_CHANGE#------------------------------------------------------- ------------------/home/oracle/app/oracle/oradata/tonytest/users01.dbf 11795798023082/home/oracle/app/oracle/oradata/tonytest/user02.dbf 117957980230823. Stop SCN (正常datafile在read-write mode运作下,last_change#一定是null)
Stop scn记录在数据文件头上。当数据库处在打开状态时,stop scn被设成最大值0xffff.ffffffff。在数据库正常关闭过程中,stop scn被设置成当前系统的最大scn值。在数据库打开过程中,Oracle会比较各文件的stop scn和checkpoint scn,如果值不一致,表明数据库先前没有正常关闭,需要做恢复。
123456 select name,last_change# from v$datafile where name like '%user%';NAME LAST_CHANGE#------------------------------------------------------- ------------/home/oracle/app/oracle/oradata/tonytest/users01.dbf/home/oracle/app/oracle/oradata/tonytest/user02.dbf一个SCN在datafile header内:
1. Start SCN
123456 select name,checkpoint_change# from v$datafile_header where name like '%user%';NAME CHECKPOINT_CHANGE#------------------------------------------------------- ------------------/home/oracle/app/oracle/oradata/tonytest/users01.dbf 11795798023082/home/oracle/app/oracle/oradata/tonytest/user02.dbf 11795798023082注:为什么储存在control file中要分为两个地方(system checkpoint scn, datafile checkpoint scn?)。当把一个tbs设为read-only时,他的scn会冻结停止,此时datafile checkpoint scn是不会再递增改变的,但是整体的system checkpoint scn却仍然会不断递增前进。所以这是为什么需要分别在两个地方储存SCN。
正常shutdown database后,SCN会发生什么变化?
|
|
补充:
- Commit SCN
当用户提交commit命令后,系统将当前scn赋给该transaction。这些信息都反映在redo buffer中,并马上更新到redo log 文件里。- Offline SCN
除了System tablespace以外的任何表空间,当我们执行SQL>alter tablespace … offline normal
命令时,就会触发一个checkpoint,将内存中的dirty buffer写入磁盘文件中。Checkpoint完成后,数据文件头会更新checkpoint scn和offline normal scn值。其中数据库文件头的checkpoint scn值可通过查询列x$kccfe.fecps得到。
如果执行SQL>alter tablespace …offline
命令时采用temporary或 immediate选项,而不用normal选项时,offline normal scn会被设成0。这样当数据库重启后通过resetlog方式打开时,该表空间就无法再改回在线状态。- Checkpoint SCN
当数据库内存的脏数据块(dirty blocks)写到各数据文件中时,就发生一次checkpoint。数据库的当前checkpoint scn值存在x\$kccdi.discn中。Checkpoint scn在数据库恢复中起着至关重要的作用。无论你用何种办法恢复数据库,只有当各个数据库文件的checkpoint scn都相同时,数据库才能打开。
虽然参数_allow_resetlogs_corruption
可以在checkpoint scn不一致时强制打开数据库,但是这样的数据库在open后必须马上作全库的export,然后重建数据库并import数据。- Resetlog SCN
数据库不完全恢复时,在指定时间点后的scn都无法再应用到数据库中。Resetlog时的scn就被设成当前数据库scn,redo log也会被重新设置。- High and Low SCN
Oracle的Redo log会顺序纪录数据库的各个变化。一组redo log文件写满后,会自动切换到下一组redo log文件。则上一组redo log的high scn就是下一组redo log的low scn。
在视图v\$log_history中,sequence#代表redo log的序列号,first_change#表示当前redo log的low scn,列next_change#表示当前redo log的high scn。
总结:
- 在control file,redo log,data file中都存在SCN值;
- 数据库open时,检查control file中记录的SCN值与数据文件,redo log文件是否一致,如果是,数据库打开,否则,提示错误;假如数据文件SCN值小于control file中的SCN值则提示该数据文件需要介质恢复;
- redo log 中存在低SCN,高SCN值两种,当前的redo log文件的高SCN值为无穷大;日志发生切换时,高SCN值更新为系统当前SCN值,新日志文件低SCN值为前日志文件高SCN值加1,高SCN值仍然为去穷大;数据库发生变化,则写redo log文件,同时SCN值会加1。
- 检查点发生时,CKPT更新数据文件头。
3.2 Oracle SCN机制解析
SCN(System Chang Number)作为oracle中的一个重要机制,在数据恢复、Data Guard、Streams复制、RAC节点间的同步等各个功能中起着重要作用。理解SCN的运作机制,可以帮助你更加深入地了解上述功能。
在理解SCN之前,我们先看下oracle事务中的数据变化是如何写入数据文件的:
- 事务开始;
- 在buffer cache中找到需要的数据块,如果没有找到,则从数据文件中载入buffer cache中;
- 事务修改buffer cache的数据块,该数据被标识为“脏数据”,并被写入log buffer中;
- 事务提交,LGWR进程将log buffer中的“脏数据”写入redo log file中;
- 当发生checkpoint,CKPT进程更新所有数据文件的文件头中的信息,DBWn进程则负责将Buffer Cache中的脏数据写入到数据文件中。
经过上述5个步骤,事务中的数据变化最终被写入到数据文件中。但是,一旦在上述中间环节时,数据库意外宕机了,在重新启动时如何知道哪些数据已经写入数据文件、哪些没有写呢(同样,在DG、streams中也存在类似疑问:redo log中哪些是上一次同步已经复制过的数据、哪些没有)?SCN机制就能比较完善的解决上述问题。
SCN是一个数字,确切的说是一个只会增加、不会减少的数字。正是它这种只会增加的特性确保了Oracle知道哪些应该被恢复、哪些应该被复制。
总共有4种SCN:
- 存在于控制文件中
- 系统检查点(System Checkpoint)SCN、
- 数据文件检查点(Datafile Checkpoint)SCN、
- 结束SCN(Stop SCN)、
- 存在于数据文件的文件头中
- 开始SCN(Start SCN)。
在控制文件中,System Checkpoint SCN是针对整个数据库全局的,因而只存在一个,而Datafile Checkpoint SCN和Stop SCN是针对每个数据文件的,因而一个数据文件就对应在控制文件中存在一份Datafile Checkpoint SCN和Stop SCN。在数据库正常运行期间,Stop SCN(通过视图v$datafile的字段last_change#可以查询)是一个无穷大的数字或者说是NULL。
在一个事务提交后(上述第四个步骤),会在redo log中存在一条redo记录,同时,系统为其提供一个最新的SCN(通过函数
dbms_flashback.get_system_change_number
可以知道当前的最新SCN),记录在该条记录中。如果该条记录是在redo log被清空(日志满做切换时或发生checkpoint时,所有变化日志已经被写入数据文件中),则其SCN被记录为redo log的low SCN。以后在日志再次被清空前写入的redo记录中SCN则成为Next SCN。当日志切换或发生checkpoint(上述第五个步骤)时,从Low SCN到Next SCN之间的所有redo记录的数据就被DBWn进程写入数据文件中,而CKPT进程则将所有数据文件(无论redo log中的数据是否影响到该数据文件)的文件头上记录的Start SCN(通过视图
v$datafile_header
的字段checkpoint_change#
可以查询)更新为Next SCN,同时将控制文件中的System Checkpoint SCN(通过视图v$database
的字段checkpoint_change#
可以查询)、每个数据文件对应的Datafile Checkpoint(通过视图v$datafile
的字段checkpoint_change#
可以查询)也更新为Next SCN。但是,如果该数据文件所在的表空间被设置为read-only时,数据文件的Start SCN和控制文件中Datafile Checkpoint SCN都不会被更新。
|
|
那系统是如何产生一个最新的SCN的?实际上,这个数字是由当时的timestamp转换过来的。每当需要产生一个最新的SCN到redo记录时,系统获取当时的timestamp,将其转换为数字作为SCN。我们可以通过函数SCN_TO_TIMESTAMP(10g以后)将其转换回timestamp:
|
|
最后,SCN除了作为反映事务数据变化并保持同步外,它还起到系统的“心跳”作用——每隔3秒左右系统会刷新一次系统SCN。
下面,在简单介绍一下SCN如何在数据库恢复中起作用。
- 数据库关闭
- 数据库在正常关闭(shutdown immediate/normal)时,会先做一次checkpoint,将log file中的数据写入数据文件中,将控制文件、数据文件中的SCN(包括控制文件中的Stop SCN)都更新为最新的SCN。
- 数据库异常/意外关闭不会或者只更新部分Stop SCN。
- 当数据库启动时,
- Oracle先检查控制文件中的每个Datafile Checkpoint SCN和数据文件中的Start SCN是否相同,
- 再检查每个Datafile Checkpoint SCN和Stop SCN是否相同。
- 如果发现有不同,就从Redo Log中找到丢失的SCN,重新写入数据文件中进行恢复。具体的数据恢复过程这里就不再赘述。
SCN作为Oracle中的一个重要机制,在多个重要功能中起着“控制器”的作用。了解SCN的产生和实现方式,帮助DBA理解和处理恢复、DG、Streams复制的问题。
最后提一句,利用SCN机制,在Oracle10g、11g中又增加了一些很实用的功能——数据库闪回、数据库负载重现等。
3.3 Oracle SCN恢复
|
|