合 Oracle SCN系列
- 前言部分
- 导读和注意事项
- Oracle SCN
- 简介
- 官方文档
- SCN的分类
- 查询4种SCN常用的SQL语句
- 文件检查点SCN (Datafile Checkpoint SCN)
- Stop SCN
- HIGH AND LOW SCN
- SCN号于数据库的启动、关闭
- 为什么需要System checkpoint SCN号与Datafile Checkpoint SCN号
- recover database using backup controlfile
- 查看系统当前SCN
- SCN与时间的相互转换(SCN_TO_TIMESTAMP与TIMESTAMP_TO_SCN)
- SMON_SCN_TIME
- 实例恢复(INSTANCE RECOVERY)和介质恢复(MEDIA RECOVERY)
- 实例恢复
- RAC中的实例恢复
- 介质恢复
- 实例恢复和介质恢复的区别
前言部分
导读和注意事项
各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,\~O(∩_∩)O\~:
① Oracle中的SCN是什么?(重点)
② 如何查询SCN?(重点)
③ SCN有哪些分类?(重点)
④ SCN和系统恢复的关系?(重点)
④ 实例恢复和介质恢复的区别是什么?RAC中的实例恢复是什么样的?(重点)
⑥ SCN和时间的转换
⑦ SMON_SCN_TIME系统表的认识
⑧ 不完全恢复的一些分类及其写法
Oracle SCN
简介
SCN(System Change Number,系统改变号)是一个由系统内部维护的序列号。当系统需要更新的时候自动增加,它是系统中维持数据的一致性和顺序恢复的重要标志,是数据库非常重要的一种数据结构。SCN的最大值是0xffff.ffffffff。在数据库中SCN作为一种时钟机制来标记数据库动作,比如当事务的发生,数据库会用一个SCN来标记它。同时这个SCN在数据库全局也是唯一的,它随时间的增长而增长除非重建数据库。
在数据库中,SCN可以说是无处不在,数据文件头,控制文件,数据块头,日志文件等等都标记着SCN。也正是这样,数据库的一致性维护和SCN密切相关。不管是数据的备份,恢复都是离不开SCN的。
官方文档
A system change number (SCN) is a logical, internal time stamp used by Oracle Database. SCNs order events that occur within the database, which is necessary to satisfy the ACID properties of a transaction. Oracle Database uses SCNs to mark the SCN before which all changes are known to be on disk so that recovery avoids applying unnecessary redo. The database also uses SCNs to mark the point at which no redo exists for a set of data so that recovery can stop.
SCNs occur in a monotonically increasing sequence. Oracle Database can use an SCN like a clock because an observed SCN indicates a logical point in time and repeated observations return equal or greater values. If one event has a lower SCN than another event, then it occurred at an earlier time with respect to the database. Several events may share the same SCN, which means that they occurred at the same time with respect to the database.
Every transaction has an SCN. For example, if a transaction updates a row, then the database records the SCN at which this update occurred. Other modifications in this transaction have the same SCN. When a transaction commits, the database records an SCN for this commit.
Oracle Database increments SCNs in the system global area (SGA). When a transaction modifies data, the database writes a new SCN to the undo data segment assigned to the transaction. The log writer process then writes the commit record of the transaction immediately to the online redo log. The commit record has the unique SCN of the transaction. Oracle Database also uses SCNs as part of its instance recovery and media recovery mechanisms.
怎么理解这个“SCN(系统变更号)是供Oracle数据库使用的一个逻辑的、内部的时间戳”呢?要理解这个先需要理解Oracle中的事务(Transaction)和数据一致性(Data Consistency)的概念。
先说说数据一致性的概念。数据一致性指的是数据的可用性。比如说管理一个财务的系统,需要从A账户将100元转入到B账户,正常的操作是从A账户减去100元,然后给B账户加上100元,如果这两步操作都正常完成了,那我们可以说完成转账操作之后的数据是一致可用的;但是如果在操作的过程中出了问题,A账户的100元给减掉了,但是B账户却没有加上100元,这样的情况下产生的结果数据就有问题了,因为部分操作的失败导致了数据的不一致而不可用,在实际中肯定是要避免这种让数据不一致的情况发生的。在Oracle数据库中,保证数据一致性的方法就是事务。
事务是一个逻辑的、原子性的作业单元,通常由一个或者是多个SQL组成,一个事务里面的所有SQL操作要么全部失败回滚(Rollback),要么就是全部成功提交(Commit)。就像上面转账的例子,为保证数据的一致性,就需要将转账的两步操作放在一个事务里面,这样不管哪个操作失败了,都需要将所有已进行的操作回滚,以保证数据的可用性。进行事务管理是数据库区别于别的文件系统的一个最主要的特征,在数据库中事务最主要的作用就是保证了数据的一致性,每次事务的提交都是将数据库从一种一致性的状态带入到另外一种一致性的状态中,SCN就是用来对数据库的每个一致状态进行标记的,每当数据库进入到一个新的一致的状态,SCN就会加1,也就是每个提交操作之后,SCN都会增加。也许你会想为什么不直接记录事务提交时候的时间戳呢?这里面主要是涉及了两个问题,一个是时间戳记录的精度有限,再一个就是在分布式系统中记录时间戳会存在系统时钟同步的问题,详细的讨论可以查看Ordering Events in Oracle。
SCN在数据库中是一个单一的不断的随着数据库一致性状态的改变而自增的序列。正如一个时间戳代表着时间里面的某一个固定的时刻点一样,每一个SCN值也代表着数据库在运行当中的一个一致性的点,大的SCN值所对应的事务总是比小SCN值的事务发生的更晚。因此把SCN说成是Oracle数据库的逻辑时间戳是很恰当的。
SCN的分类
严格来说SCN是没有分类的,之所以会有不同类型的SCN并不是说这些SCN的概念不一样,而是说不同分类的SCN代表的意义不一样,不管什么时候SCN所指代的都是数据库的某个一致性的状态。就像我们给一天中的某个时间点定义上班时间、另外的某个时间点定义成下班时间一样,数据库Checkpoint发生点的SCN被称为Checkpoint SCN,仅此而已。
SCN可以分为4类,系统检查点SCN(System Checkpoint SCN)、文件检查点SCN(Datafile Checkpoint SCN)、开始SCN(Start SCN)和结束SCN(Stop SCN),参考如下表格:
查询4种SCN常用的SQL语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | col status for a10 select GROUP# ,SEQUENCE#,STATUS,FIRST_CHANGE#,FIRST_TIME from v$log; SELECT A.FILE#, A.NAME, (SELECT CHECKPOINT_CHANGE# FROM V$DATABASE) SYSTEM_CKPT_SCN, A.CHECKPOINT_CHANGE# DF_CKPT_SCN, A.LAST_CHANGE# END_SCN, B.CHECKPOINT_CHANGE# START_SCN, B.RECOVER, A.STATUS FROM V$DATAFILE A, V$DATAFILE_HEADER B WHERE A.FILE# = B.FILE#; SELECT FILE#,ONLINE_STATUS,CHANGE#,ERROR FROM V$RECOVER_FILE; |
文件检查点SCN (Datafile Checkpoint SCN)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | SYS@lhrdb> select file#,checkpoint_change# from v$datafile; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 9026292 2 9026292 3 9026292 4 9026292 5 9026292 6 9026292 7 9026292 7 rows selected. SYS@lhrdb> alter tablespace users read only; Tablespace altered. SYS@lhrdb> select file#,checkpoint_change# from v$datafile; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 9026292 2 9026292 3 9026292 4 9028165 5 9026292 6 9026292 7 9026292 7 rows selected. SYS@lhrdb> select checkpoint_change# from v$database; CHECKPOINT_CHANGE# ------------------ 9026292 |
可以看到4号文件也就是users表空间所属的文件scn值和其他文件不一致,且比系统检查点的scn要大。
Stop SCN
Stop scn记录在数据文件头上。当数据库处在打开状态时,stop scn被设成最大值0xffff.ffffffff。在数据库正常关闭过程中,stop scn被设置成当前系统的最大scn值。在数据库打开过程中,Oracle会比较各文件的stop scn和checkpoint scn,如果值不一致,表明数据库先前没有正常关闭,需要做恢复。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | SYS@lhrdb> SELECT TABLESPACE_NAME,STATUS FROM DBA_TABLESPACES; TABLESPACE_NAME STATUS ------------------------------ --------- SYSTEM ONLINE SYSAUX ONLINE UNDOTBS1 ONLINE TEMP ONLINE USERS READ ONLY EXAMPLE ONLINE TS_MIG_CHAIN_LHR ONLINE TS_TESTBLOCKLHR ONLINE 8 rows selected. SYS@lhrdb> SELECT FILE#,LAST_CHANGE# FROM V$DATAFILE; FILE# LAST_CHANGE# ---------- ------------ 1 2 3 4 9028165 5 6 7 7 rows selected. |
可以看到除了USERS表空间的结束SCN不为空,其他数据文件的结束SCN为空。
将数据库至于MOUNT状态,由于该状态下所有的数据文件都不可写,故MOUNT状态下所有的数据文件都具有结束SCN。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | SYS@lhrdb> startup mount ORACLE instance started. Total System Global Area 1720328192 bytes Fixed Size 2247072 bytes Variable Size 452986464 bytes Database Buffers 1258291200 bytes Redo Buffers 6803456 bytes Database mounted. SYS@lhrdb> SELECT FILE#,LAST_CHANGE# FROM V$DATAFILE; FILE# LAST_CHANGE# ---------- ------------ 1 9048847 2 9048847 3 9048847 4 9028165 5 9048847 6 9048847 7 9048847 7 rows selected. SYS@lhrdb> alter tablespace users read write; Tablespace altered. SYS@lhrdb> SELECT FILE#,LAST_CHANGE# FROM V$DATAFILE; FILE# LAST_CHANGE# ---------- ------------ 1 2 3 4 5 6 7 7 rows selected. SYS@lhrdb> startup force mount ORACLE instance started. Total System Global Area 1720328192 bytes Fixed Size 2247072 bytes Variable Size 452986464 bytes Database Buffers 1258291200 bytes Redo Buffers 6803456 bytes Database mounted. SYS@lhrdb> SELECT FILE#,LAST_CHANGE# FROM V$DATAFILE; FILE# LAST_CHANGE# ---------- ------------ 1 2 3 4 5 6 7 7 rows selected. |
HIGH AND LOW SCN
ORACLE的REDO LOG会顺序纪录数据库的各个变化。一组REDO LOG文件写满后,会自动切换到下一组REDO LOG文件。则上一组REDO LOG的HIGH SCN就是下一组REDO LOG的LOW SCN。在CURRENT LOG中HIGH SCN为无穷大。
在视图V\$LOG_HISTORY中,SEQUENCE#代表REDO LOG的序列号,FIRST_CHANGE#表示当前REDO LOG的LOW SCN,列NEXT_CHANGE#表示当前REDO LOG的HIGH SCN。
可通过查询V\$LOG_HISTORY查看 LOW SCN和 HIGH SCN。
1 2 3 4 5 6 7 8 9 10 11 12 13 | SYS@lhrdb> set pagesize 9999 SYS@lhrdb> SELECT RECID,SEQUENCE#,FIRST_CHANGE#,NEXT_CHANGE# FROM V$LOG_HISTORY WHERE ROWNUM<=6; RECID SEQUENCE# FIRST_CHANGE# NEXT_CHANGE# ---------- ---------- ------------- ------------ 272 272 7486197 7510243 273 273 7510243 7527538 274 274 7527538 7539409 275 275 7539409 7556740 276 276 7556740 7572195 277 277 7572195 7581847 6 rows selected. |
查看CURRNET REDO LOG中的HIGH SCN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | SYS@lhrdb> COL MEMBER FORMAT A50 SYS@lhrdb> SELECT VF.MEMBER,V.STATUS,V.FIRST_CHANGE# FROM V$LOGFILE VF,V$LOG V 2 WHERE VF.GROUP#=V.GROUP# 3 AND V.STATUS='CURRENT'; MEMBER STATUS FIRST_CHANGE# -------------------------------------------------- ---------------- ------------- +DATA/lhrdb/onlinelog/group_4.798.923841413 CURRENT 9069089 +DATA/lhrdb/onlinelog/group_4.797.923841415 CURRENT 9069089 SYS@lhrdb> ALTER SYSTEM DUMP LOGFILE '+DATA/lhrdb/onlinelog/group_4.797.923841415'; System altered. SYS@lhrdb> oradebug setmypid Statement processed. SYS@lhrdb> oradebug tracefile_name /oracle/app/oracle/diag/rdbms/lhrdb/lhrdb/trace/lhrdb_ora_8388948.trc |
查看转储文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | DUMP OF REDO FROM FILE '+DATA/lhrdb/onlinelog/group_4.797.923841415' Opcodes *.* RBAs: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff SCNs: scn: 0x0000.00000000 thru scn: 0xffff.ffffffff Times: creation thru eternity FILE HEADER: Compatibility Vsn = 186647552=0xb200400 Db ID=959319562=0x392e0e0a, Db Name='LHRDB' Activation ID=959339270=0x392e5b06 Control Seq=96545=0x17921, File size=204800=0x32000 File Number=4, Blksiz=512, File Type=2 LOG descrip:"Thread 0001, Seq# 0000001090, SCN 0x0000008a6221-0xffffffffffff" thread: 1 nab: 0xffffffff seq: 0x00000442 hws: 0x2 eot: 1 dis: 0 resetlogs count: 0x36a23c8c scn: 0x0000.000e20dc (925916) prev resetlogs count: 0x3155bebd scn: 0x0000.00000001 (1) Low scn: 0x0000.008a6221 (9069089) 10/11/2016 16:46:41 Next scn: 0xffff.ffffffff 01/01/1988 00:00:00 Enabled scn: 0x0000.000e20dc (925916) 07/07/2016 19:39:56 Thread closed scn: 0x0000.008a6221 (9069089) 10/11/2016 16:46:41 Disk cksum: 0xc14c Calc cksum: 0xc14c Terminal recovery stop scn: 0x0000.00000000 Terminal recovery 01/01/1988 00:00:00 Most recent redo scn: 0x0000.00000000 Largest LWN: 0 blocks End-of-redo stream : No Unprotected mode Miscellaneous flags: 0x800000 Thread internal enable indicator: thr: 0, seq: 0 scn: 0x0000.00000000 Zero blocks: 0 Format ID is 1 redo log key is 47e6cd1abd3a43fd864d2b94ae9a8128 redo log key flag is 5 Enabled redo threads: 1 |
当前最新的数据库scn值可通过如下命令查看:
1 2 3 4 5 | SYS@lhrdb> select dbms_flashback.get_system_change_number from dual; GET_SYSTEM_CHANGE_NUMBER ------------------------ 9069555 |
如果需要进行实例恢复,则需要恢复的记录为9069089至9069555中redo log中的记录。
SCN号于数据库的启动、关闭
Scn号与Oracle数据库恢复过程有着密切的关系,只有很好地理解了这层关系,才能深刻地理解恢复的原理。CKPT进程在checkpoint发生时,将当时的SCN号写入数据文件头和控制文件,同时通知DBWR进程将数据块写到数据文件。
CKPT进程也会在控制文件中记录RBA(redo block address),以标志Recovery需要从日志中哪个地方开始。
1.在数据库的启动过程中,当System Checkpoint SCN=Datafile Checkpoint SCN=Start SCN的时候,Oracle数据库是可以正常启动的,而不需要做任何的MEDIA RECOVERY。而如果三者当中有一个不同的话,则需要做MEDIA RECOVERY。Oracle在启动过程中首先检查是否需要MEDIA RECOVERY,然后再检查是否需要INSTANCE RECOVERY。
2.那什么时候需要做INSTANCE RECOVERY呢?其实在正常OPEN数据库的时候,Oracle会将记录在控制文件中的每一个数据文件头的End SCN都设置为#FFFFFF(NULL),那么如果数据库进行了正常关闭比如(shutdown or shutdown immediate)这个时候,系统会执行一个检查点,这个检查点会将控制文件中记录的各个数据文件头的End SCN更新为当前online数据文件的各个数据文件头的Start SCN,也就是End SCN=Start SCN,如果再次启动数据库的时候发现二者相等,则直接打开数据库,并再次将End SCN设置为#FFFFFF(NULL),那么如果数据库是异常关闭,那么CHECKPOINT就不会执行,因此再次打开数据库的时候End SCN\<>Start SCN这个时候就需要做实例恢复。如果数据库异常关闭的话,则END SCN号将为NULL.则需要做instance recovery。
为什么需要System checkpoint SCN号与Datafile Checkpoint SCN号
为什么ORACLE会在控制文件中记录System checkpoint SCN号的同时,还需要为每个数据文件记录Datafile Checkpoint SCN号?
原因有二:
1.对只读表空间,其数据文件的Datafile Checkpoint SCN、Start SCN和END SCN号均相同。这三个SCN在表空间处于只读期间都将被冻结。
2.如果控制文件不是当前的控制文件,则System checkpoint会小于Start SCN或END SCN号。记录这些SCN号,可以区分控制文件是否是当前的控制文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | SYS@lhrdb> alter tablespace users read only; Tablespace altered. SYS@lhrdb> SELECT A.FILE#, 2 A.NAME, 3 (SELECT CHECKPOINT_CHANGE# FROM V$DATABASE) SYSTEM_CKPT_SCN, 4 A.CHECKPOINT_CHANGE# DF_CKPT_SCN, 5 A.LAST_CHANGE# END_SCN, 6 B.CHECKPOINT_CHANGE# START_SCN, 7 B.RECOVER, 8 A.STATUS 9 FROM V$DATAFILE A, V$DATAFILE_HEADER B 10 WHERE A.FILE# = B.FILE#; FILE# NAME SYSTEM_CKPT_SCN DF_CKPT_SCN END_SCN START_SCN REC STATUS ---------- ------------------------------------------------------------ --------------- ----------- ---------- ---------- --- ---------- 1 +DATA/lhrdb/datafile/system.347.916601927 9225394 9225394 9225394 NO SYSTEM 2 +DATA/lhrdb/datafile/sysaux.340.916601927 9225394 9225394 9225394 NO ONLINE 3 +DATA/lhrdb/datafile/undotbs1.353.916601927 9225394 9225394 9225394 NO ONLINE 4 +DATA/lhrdb/datafile/users.445.916601927 9225394 9229175 9229175 9229175 NO ONLINE 5 +DATA/lhrdb/datafile/example.416.916602001 9225394 9225394 9225394 NO ONLINE 6 +DATA/lhrdb/datafile/ts_mig_chain_lhr.471.919677645 9225394 9225394 9225394 NO ONLINE 7 /oracle/app/oracle/oradata/lhrdb/testblocklhr01.dbf 9225394 9225394 9225394 NO ONLINE 7 rows selected. |