玩Oracle也有2年的时间了,零零散散的也整理一些资料。东西一多了,就理不清楚。所以结合张晓明的《大话OracleRAC》的一些内容,和自己整理的一些笔记,对Oracle的备份和恢复做了一个系统的整理。也是自己对知识的一个巩固吧。
一.准备知识
先来看一些准备知识,了解Oracle的物理结构,有如下4种。
1.数据文件和数据块
Oracle数据库的存储空间是用表空间来表示的,表空间只是一个逻辑概念,而物理上每个表空间是由磁盘文件组成,这些文件叫做数据文件(Datafile),每个表空间可以由一个到多个数据文件组成,每个数据文件被划分为若干个最小的存储单位:数据块(datablock)。
具体参考我的blog:表空间(tableSpace)段(segment)盘区(extent)块(block)关系
http://blog.csdn.net/tianlesoftware/archive/2009/12/13/4962476.aspx
Oracle的用户数据是写到数据块上的,Oracle是在SGA上操作数据的,修改数据或者添加数据都是在内存中进行,这些被修改的内存不会立即写入磁盘,而是以特定的时间间隔被写入磁盘。如果哦数据库正常关闭,则在关闭之前将内存中的数据同步到磁盘,这时数据状态是一致的。如果数据库不正常关闭(如宕机,shutdownabort),内存中的内容没有完全写回磁盘,这时数据文件是不一致的。如果数据文件是从备份中恢复出来的,数据文件也是不一致的,不一致性的数据文件必须恢复到一致的状态。
2.日志文件
Oracle数据库日志文件包括联机日志和归档日志,这些文件都是用来记录数据库修改历史的。Oracle数据库至少要有两组联机日志,联机日志循环使用,当一组联机日志写满后,就要切换到另一组联机日志,后者的内容就会被覆盖,这个过程叫作日志切换(LogSwitch),在日志切换时会触发检查点(CheckPoint)。
数据库的修改操作要记录到日志文件中,并且这个记录动作是在修改数据之前进行的,正因为日志文件中记录了所有的修改历史,因此如果有过去某个时点的备份文件,并且有从那是到当前的所有日志文件,就可以通过在备份文件上“重演”这些日志的方式,把数据文件恢复到当前状态或者之间的任何时点的状态。
日志线程(RedoThread):
每个实例用到的联机日志就是一个RedoThread,单实例有且仅有一个RedoThread。在RAC环境下,每个实例都需要自己的联机日志,也就是每个实例都有自己的RedoThread。这种每实例一个RedoThread的设计就是为了避免实例间共享Redo文件引发的竞争,提高系统性能。但是这也带了一个问题,就是用RMAN备份RAC的时候,需要所有的日志文件。故需要在两个节点上互相把日志传送到另一个节点。
Thread这个参数用来指定实例使用的RedoThread线程号。一般和该实例的INSTANCE_NUMBER参数相同。通过视图V$LOG的Thread#列可以确定日志组所属的线程。
注意:因为RAC环境下有多个日志线程,所以在添加日志时必须指定线程号。
SQL>alterdatabaseaddlogfilethread1group5('/oracle/oradata/redo5')size50m;
在RAC环境下,用户操作是分布在多个实例之间的,各实例都有自己的联机日志,恢复时必须把所有实例的联机日志都合并,把RedoLogRecord按照SCN排序,才能整理出准确的用户操作记录,所以RAC的联机日志必须放在共享存储上,以保证实例都能访问其他实例的联机日志。
在看一个sql的查询结果:
SQL>select*fromv$log;
GROUP#THREAD#SEQUENCE#BYTESMEMBERSARCSTATUS
-------------------------------------------------------------------------
11245851048576001YESACTIVE
21245831048576001YESINACTIVE
31245841048576001YESINACTIVE
81245861048576001NOCURRENT
从查询结果上,我们可以看到联机日志有3个状态。
INACTIVE:表示DBWR已经做完,该日志包含的数据修改已经写到数据文件
ACTIVE:DBWR没有做完,数据还没有写到数据文件。
CURRENT:当前正在使用的日志。没有DBWR操作。
RedoLogCheckpoint和SCN关系
http://blog.csdn.net/tianlesoftware/archive/2010/01/25/5251916.aspx
RedoLog和Checkpointnotcomplete
http://blog.csdn.net/tianlesoftware/archive/2009/12/01/4908066.aspx
Oracle归档与非归档的切换
http://blog.csdn.net/tianlesoftware/archive/2009/10/19/4693470.aspx
logfilesync(日志文件同步)与Logfileparallelwrite等待事件
http://blog.csdn.net/tianlesoftware/archive/2009/12/02/4916671.aspx
3.控制文件
控制文件记录了数据库的物理结构和状态(比如数据文件名,每个数据文件的检查点号,联机状态),包括备份和恢复的信息也记录在控制文件中。恢复过程要根据控制文件中的信息,比如数据库的检查点,当前联机日志,数据文件检查点等来进行恢复操作,如果控制文件丢失,则恢复的过程会很艰难。
控制文件里包含的具体信息,参考我的Blog:
Oracle控制文件
http://blog.csdn.net/tianlesoftware/archive/2009/12/13/4974440.aspx
4.UndoSegment
修改记录过程中,记录修改之前的状态会被记录到UndoSegment中,这条记录叫作前镜像(beforeimages)。当需要撤销修改比如执行Rollback时,就用这条前镜像覆盖现有记录,对于Insert操作,前镜像就是一个空记录,对于Undate,Delete操作,前镜像就是修改之前的记录。
在数据库恢复过程中,日志和UndoSegment共同起作用,二者保证了最终恢复的一致状态。二者也对应了恢复的两个阶段:前滚(Roforware)和回滚(Rollback)。在前滚阶段,在文件上重演日志内容,以把文件恢复到数据库关闭时的状态,但是数据库关闭时可能有很多修改操作没有提交,这些操作必须进行回滚,这就要利用UndoSegment的内容。
Oracleundo回滚段管理
http://blog.csdn.net/tianlesoftware/archive/2009/11/30/4901666.aspx
二.备份
备份是指数据的拷贝,这个拷贝可以用来重建数据库。备份可以分为物理备份和逻辑备份。
物理备份:指对数据文件,控制文件,联机日志文件等文件进行物理拷贝的方法,这种方法是在文件层进行的,通过冗余的文件备份来体统数据保护。物理备份又可分为联机备份(也叫作联机热备)和脱机备份(也称冷备)。
逻辑备份:利用Oracle提供的导出工具把重要数据导出到文件,以后恢复时在利用工具把数据重新导入到数据库中,这种保护是在数据层进行的。该类工具有:exp/imp,expdp/impdp(10g以后版本)。
物理备份是最强健的数据保护方也,也是备份策略中首选的方法,逻辑备份只能作为物理备份的补充手段,不足以保护数据丢失。
物理备份又可分为用户管理备份(User-ManagedBackup)和RMAN备份(RecoveryManager)。前者是联合使用SQL命令和OS的cp命来进行文件备份。Rman备份指利用RMAN工具来进行备份。
Rman备份有几点好处:
1.增量备份
2.数据块恢复:可以在新进行数据块恢复,不必进行数据文件恢复,提高系统的可用性。
3.压缩备份
4.加密备份
具体用法参考blog:
RMAN备份与恢复实例
http://blog.csdn.net/tianlesoftware/archive/2009/10/20/4699320.aspx
OracleRman命令详解(Listreportbackupconfigure)
http://blog.csdn.net/tianlesoftware/archive/2009/12/13/4976998.aspx
OracleRman跨resetlogs版本恢复
http://blog.csdn.net/tianlesoftware/archive/2009/10/17/4682463.aspx
ORACLE数据库逻辑备份简单EXP/IMP
http://blog.csdn.net/tianlesoftware/archive/2009/10/24/4718366.aspx
Oracle10gEXPDP和IMPDP使用说明
http://blog.csdn.net/tianlesoftware/archive/2009/10/16/4674224.aspx
三.恢复
3.1理论知识:
Oracle在运行过程中,所有对于数据的修改都是在内存中进行,Oracle每要修改一个记录必须先把记录所在的数据块加载到内存中,然后在内存中进行修改。但是提交(commit)时,修改的数据块不会立即写回磁盘。基于性能考虑,Oracle是采用“延时写”的算法定期批量的把数据块写回磁盘。因此在数据库运行过程中,内存的内容总是比磁盘数据新。当数据库正常关闭时(ShutdownImmediate,shutdownnormal,shutdowntracsactional),Oracle会把SGA内容全部写回磁盘后才关闭数据库,这时内存和磁盘就完全同步了。所以正常关闭数据库后数据不会丢失,但是如果数据库是异常关闭(突然短线,shutdownabort),内存中的数据来不及同步到磁盘,这是就会产生了数据不一致,Oracle在次打开数据库时,就需要进行实例恢复。
Oracle的Redo机制保证了数据库恢复的可行性,在修改数据之前,代表本次修改操作的Redo记录必须先被保存下来(WriteAheadLogging),然后才真正修改数据记录。在处理commit语句时,Oracle会在Logbuffer产生一条commit记录,为了保证事务的持久化,所有Redo记录和这一条commit记录都要被写到磁盘的联机日志文件(LogForceAtcommit),但是数据块(DataBlock)不必写回磁盘。如果联机日志空间不够,还会触发日志切换(LogSwitch),旧日志的检查点必须完成才能被覆盖,如果采用归档模式,这个日志还必须完成归档才能覆盖。
这些日志中都会带有SCN,SCN类似于时间戳,Oracle按照SCN对日志内容进行排序,就可以得到操作历史,Oracle也是根据SCN来判断数据文件是否需要恢复的。
数据库在正常运行时,每个数据文件的终止SCN(STOPSCN)会被设置为无穷大(NULL),而其他的那些SCN应该完全一样。如果数据库正常关闭,关闭之前会执行一个检查点动作,每个数据文件的终止SCN会被设置成启动SCN(StartSCN)。如果数据库异常关闭,终止SCN来不及设置为启动SCN,仍然保持NULL。
当cleanshutdown时,checkpoint会进行,并且此时datafile的stopscn和startscn会相同。等到我们开启数据库时,Oracle检查datafileheader中的startscn和存于controlfile中的datafile的scn是否相同,如果相同,接着检查startscn和stopscn是否相同,如果仍然相同,数据库就会正常开启,否则就需要recovery...等到数据库开启后,储存在controlfile中的stopscn就会恢复为NULL值,此时表示datafile是open在正常模式下了。
如果不正常SHUTDOWN(shutdownabort),则mount数据库后,你会发现stopscn并不是等于其它位置的scn,而是等于NULL,这表示Oracle在shutdown时没有进行checkpoint,下次开机必须进行crashrecovery。
注意:当发生checkpoint时,会把SCN写到四个地方去。三个地方于controlfile内,一个在datafileheader。
Controlfile三个地方为
1.SystemcheckpointSCN
2.2.DatafilecheckpointSCN
3.StopSCN
另外一个地方在datafileheader内
4.StartSCN
更多内容参看blog:RedoLogCheckpoint和SCN关系
http://blog.csdn.net/tianlesoftware/archive/2010/01/25/5251916.aspx
Oracle恢复可以分成实例恢复(InstanceRecovery),介质恢复(MediaRecovey),其中介质恢复又可分为完全恢复(CompleteRecovery)和不完全恢复(IncompleteRecovery)。
3.2恢复种类
3.2.1InstanceRecovery--由Oracle自动完成,无需DBA干预
如果实例异常关闭(宕机,shutdownabort),并且数据文件,控制文件,联机日志都没有丢失。在下次启动时,要利用联机日志的内容进行恢复,这种恢复就是实例恢复(InstanceRecovery)。
InstanceRecovery主要包括3个阶段:
1)根据联机日志内容进行Rollover。
2)打开数据库,提供服务
3)SMON或者用户进程进行Rollback。
3.2.2MediaRecovery
如果发生数据文件丢失或者破坏,就需要使用备份和归档日志来进行恢复,这种恢复就是介质恢复,它需要有备份,归档日志,联机日志一起才能完成。又分为安全恢复和不完全恢复两种。
3.2.3CrashRecovery--由Oracle自动完成。
InstanceRecovery是实例发生Crash后进行的Recovery,这种恢复是在故障节点进行,而RAC中的CrashRecovery是某个实例发生Crash后在其他实例上进行的Recovery。这种Recovery有一个特殊要求:在健康节点执行CrashRecovery时,必须要保证故障节点不能在对共享数据进行操作,也就是要对故障节点进行IO隔离(IOFencing),这是由CSS服务来保证的。
在CrashRecovery过程中PCMLock起到了重要作用,恢复实例(执行Recovery动作的实例)根据数据块的PCM-Lock状态来决定数据块是否需要进行恢复。
CrashRecovery可分为3个阶段:
1)First-PassLogRead
2)RecoveryClaimLocking
3)Second-PassLogRead
3.2.4OnlineBlockRecovery
OnlineBlockRecovery是RAC所特有的,如果某个用户进程在修改数据时异常死掉,导致SGA的Databuffer数据不一致,或者说DataBuffer被破坏,这时就会触发OnlineBlockRecovery,这个动作可有PMON进程或者前台进程完成。这个恢复过程需要一个恢复起点,这个起点就是最近的PastImage。
3.3介质恢复
介质恢复指磁盘介质发生损坏,导致数据文件无法访问,这时必须利用备份文件在新的磁盘上恢复出数据文件。
3.3.1完全恢复
它是把数据库恢复到发生故障时的状态,名字中的完全指没有任何数据损失,要实现这个目标,必须满足一定的条件:备份,从备份之后的所有归档日志,联机日志都可用。
完全恢复是最简单的一种恢复,只需要两个命令:restoredatabase和recoverdatabase。
这2个命令的具体用法参考我的Blog:RMAN备份与恢复实例,里面有详细的例子
http://blog.csdn.net/tianlesoftware/archive/2009/10/20/4699320.aspx
在次补充一点知识:RECOVERDATABASEUNTILCANCEL和RECOVERDATABASEUNTILCANCELUSINGBACKUPCONTROLFILE区别
1)RECOVERDATABASEUNTILCANCEL
==>DATAFILEHEADERSCN一定会小于CONTROLFILE的DATAFILESCN
如果你有进行RESTOREDATAFILE,则该RESTORE的DATAFILEHEADERSCN一定会小于目前CONTROLFILE的DATAFILESCN,此时会无法开启数据库,必须进行mediarecovery。重做archivelog直到该datafileheader的SCN=currentscn
2)RECOVERDATABASEUNTILCANCELUSINGBACKUPCONTROLFILE;
==>DATAFILEHEADERSCN一定会大于CONTROLFILE的DATAFILESCN
如果只是某TABLE被DROP掉,没有破坏数据库整体数据结构,还可以用NCOMPLETERECOVERY解决如果是某个TABLESPACEORDATAFILE被DROP掉,因为档案结构已经破坏,目前的CONTROLFILE内已经没有该DATAFILE的信息,就算你只RESTOREDATAFILE然后进行INCOMPLETERECOVERY也无法救回被DROP的DATAFILE。
只好RESOTRE之前备份的CONTROLFILE(里头被DROPDATAFILEMetadata此时还存在),不过RESTORECCONTROLFILE后此时Oracle会发现CONTROLFILE内的SYSTEMSCN会小于目前的DATAFILEHEADERSCN,也不等于目前储存于LOGFILE内的SCN,此时就必须使用RECOVERDATABASEUNTILCANCELUSINGBACKUPCONTROLFILE到DROPDATAFILEORDROPTABLESPACE之前的SCN。
3.3.2不完全恢复
不完全恢复是指数据库无法恢复到发生故障那一点的状态,而只能恢复到之前一段时间的状态,这就以为着承受一定量的数据损失。
Oracle运行时包括参数文件,控制文件,数据文件,联机日志,那么哪些文件会导致不完全恢复呢?
参数文件只是一个文本文件,丢失没有关系。控制文件通常有多个文件相互冗余。而且在做全库备份时,控制文件会被自动备份,故所有文件都损坏,也可以通过备份进行恢复,即使没有备份,也可以通过重建控制文件来恢复,也不会造成数据丢失。如果是数据文件损坏,只要有备份和备份后的完整的日志文件,也可以完成恢复,不会造成数据丢失。
联机日志比较特殊,通过前面的介绍,我们知道在数据库异常关机的情况下,它可能造成数据丢失。
我们来看一下联机日志损坏的恢复方法:
先用SQL查看一下出问题的联机日志是什么状态:
SQL>Selectthread#,group#,statusfromv$log;
1)如果是Inactive状态的联机日志,因为它里面的记录已经同步到数据文件,所以只需要把该日志删掉即可。
2)如果是Active/current状态的连接日志,因为他们里面有记录没有同步到数据文件,可以通过如下方式来恢复:
(1)关闭所有实例
(2)在受损实例上,启动到mount状态
(3)执行alterdatabaseopenresetlogs
(4)如果在第三步出现错误,并其实需要不完全恢复,就执行一下:recoverdatabaseuntilcancel
(5)实例启动成功后,启动其他实例
(6)立即对数据库进行一次全备。
说明:在做了alterdatabaseopenresetlogs;会把onlineredelogfile清空,数据文件丢失.所以这个时候要做一个全备份。resetlogs命令表示一个数据库逻辑生存期的结束和另一个数据库逻辑生存期的开始,每次使用resetlogs命令的时候,SCN不会被重置,不过oracle会重置日志序列号,而且会重置联机重做日志内容.这样做是为了防止不完全恢复后日志序列会发生冲突(因为现有日志和数据文件间有了时间差)。