ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Oracle RMAN全能备份脚本:全备+增量+归档清理+恢复验证实战

Oracle RMAN全能备份脚本:全备+增量+归档清理+恢复验证实战 简介面向Oracle数据库管理员DBA的RMAN全能备份脚本合集聚焦全备、增量备份与数据泵备份三大场景帮助运维人员快速构建规范化备份流程降低人为误操作风险确保数据库在故障或数据丢失时能够及时恢复。整套脚本以rar压缩包形式发布体积仅1KB共包含5个Shell脚本分别承担全库备份、0级增量备份、1级增量备份、数据泵逻辑导出及Linux定时调度等职责覆盖从物理备份到逻辑备份、从手动执行到自动运行的全流程。目前已有132人学习下载适合需要快速落地RMAN备份策略、兼顾效率与安全性的数据库运维人员参考。脚本结构清晰、参数注释明确可根据业务实际调整备份路径、保留策略与执行周期配合RMAN的validate命令定期验证备份集完整性有效提升备份任务的可靠性与可维护性。1. 先把 RMAN 脚本拆开一套脚本管住全备、增量与归档清理生产库里最怕的不是数据库宕了而是宕完之后发现备份是坏的。我拆过不少 DBA 手里的 RMAN 备份脚本最常见的状态是全备靠手点、增量看心情、归档日志堆到磁盘满才想起来清理。这套 Oracle RMAN 全能备份脚本解决的就是这三件事——把 level 0 全备、level 1 增量、归档日志清理、数据泵逻辑备份收进同一套 shell 编排里配上标签和日志能直接扔进 crontab 里跑。适合手里管着单实例或备库、不想再用第三方备份软件、又被领导要求备份必须可恢复的 DBA。下文所有命令我都按生产环境习惯写从策略选型一路到避坑实录照着改就能落地。2. 备份策略与 RMAN 参数选型归档模式、0 级与 1 级增量怎么搭2.1 先查数据库状态ARCHIVELOG、FORCE LOGGING 与归档频率RMAN 增量备份的前提是数据库必须运行在归档模式下。很多刚接手 Oracle 的运维兄弟第一件事就写备份脚本结果跑 level 1 增量时报错回头一查库还在 NOARCHIVELOG。所以在写脚本之前我一般先执行下面这段 SQL把数据库的运行状态摸清楚sqlplus / as sysdba EOF set linesize 200 pagesize 50 col name format a20 select name, log_mode, force_logging, open_mode from v\$database; select thread#, sequence#, status, archived from v\$log order by thread#, sequence#; select sum(blocks * block_size) / 1024 / 1024 as avg_mb_per_log from v\$archived_log where first_time sysdate - 7; EOF这段 SQL 看三件事。第一log_mode必须是ARCHIVELOG不是的话先shutdown immediate然后startup mount再alter database archivelog;否则后面所有增量策略都无从谈起。第二force_logging建议为YES特别是库里有NOLOGGING操作比如 direct load、索引重建时不强制日志会导致增量备份丢失这部分变化。第三avg_mb_per_log是过去 7 天每个归档的平均大小这个数字直接决定归档删除策略里completed before的保留天数——归档越多保留窗口越短不然备份盘很快被撑满。2.2 RMAN 增量机制0 级全备、1 级增量与快照控制文件RMAN 的增量备份有两个层级level 0和level 1。level 0 是全量基线备份所有数据文件块level 1 是增量只备份自上次备份以来发生变化的数据块。注意一点level 1 分为差异增量incremental level 1默认和累积增量incremental level 1 cumulative。差异增量只备份从上一次 level 1 或 level 0 之后的变化恢复时要按时间顺序依次应用累积增量备份从上一次 level 0 之后的所有变化恢复时只需要一个累积增量加一个 level 0链路更短。生产库里我一般用差异增量因为备份量小、跑得快前提是你得保证恢复链完整。还有一个经常被忽略的参数是快照控制文件。RMAN 备份期间需要读控制文件的一致性快照默认在 Oracle 家目录的dbs下但有备库或 DG 环境时这个快照路径不能和主库冲突。建议在备份脚本里显式指定快照控制文件位置避免在多个目录间来回找rman target / EOF configure snapshot controlfile name to /u01/backup/rman/snapcf_orcl.f; configure controlfile autobackup on; configure controlfile autobackup format for device type disk to /u01/backup/rman/ctl_%F.bak; EOF第一行指定快照控制文件路径第二行开启控制文件自动备份第三行设置自动备份的格式。%F是 RMAN 专门为控制文件设计的占位符它自动带上 DBID、日期和序列号恢复时 RMAN 能据此自动定位最新的控制文件备份。这三条配置写进脚本里等于给备份加了一道保险哪怕控制文件整个没了也能从最后一份自动备份恢复元数据。2.3 备份目录、保留策略与运行窗口评估备份目录规划这块我踩过一次大坑一开始把所有备份集堆在一个目录时间一长list backup里能看到几百个备份集磁盘满到连归档日志都写不进去。后来按日期分子目录目录结构固定成下面这样路径用途保留策略/u01/backup/rman/YYYYMMDD/RMAN 备份集保留 7 天过期由 RMAN 删除/u01/backup/rman/ctl_%F.bak控制文件自动备份保留 14 天/u01/backup/expdp/YYYYMMDD/数据泵导出文件保留 7 天/u01/backup/logs/脚本运行日志保留 30 天保留策略用 RMAN 配置而非操作系统脚本去删这是关键。很多人习惯写个find /u01/backup -mtime 7 -exec rm -rf {}这样干会出大事——RMAN 记录里的备份集文件还在但物理文件已经没了恢复时报ORA-19809找不到备份。正确做法是让 RMAN 自己管理生命周期rman target / EOF configure retention policy to recovery window of 7 days; EOF这条命令的含义是保留最近 7 天内能完成恢复所需的全部备份。比如你周日做了 level 0周一到周六做了 6 个 level 1那周四的 level 1 在周日之前是不能删的因为恢复链需要它。RMAN 会在满足 7 天恢复窗口后才把过期的备份集标记为EXPIRED。至于运行窗口评估我一般查v$rman_status里每次备份的耗时和大小再对比业务低谷期长度select session_key, input_type, status, to_char(start_time, mm-dd hh24:mi) start_t, to_char(end_time, hh24:mi) end_t, round(input_bytes/1024/1024/1024, 1) input_gb, round(output_bytes/1024/1024/1024, 1) output_gb from v$rman_status where start_time sysdate - 7 order by session_key;看到输出后如果全备要跑 3 个小时而业务低谷只有 2 小时就得考虑开并行通道或者压缩。这套脚本里默认开两个 channel 并启用compressed backupset压缩率在数据仓库类库上通常能到 3:1 到 5:1能显著缩短备份窗口。3. 脚本编排实战从全备函数到归档删除与数据泵一体化3.1 环境变量、目录结构与脚本骨架脚本的核心是把 RMAN 的重复操作封装成一个带参数的 shell 函数。先看骨架我建议所有路径变量集中放在脚本头部#!/bin/bash # rman_backup.sh - 全能备份脚本 # 用法: sh rman_backup.sh 0 # level 0 全备 # sh rman_backup.sh 1 # level 1 增量 # sh rman_backup.sh exp # 数据泵导出 export ORACLE_SIDorcl export ORACLE_HOME/u01/app/oracle/product/19c/dbhome_1 export PATH${ORACLE_HOME}/bin:${PATH} export NLS_DATE_FORMATyyyy-mm-dd hh24:mi:ss BACKUP_BASE/u01/backup/rman/$(date %Y%m%d) LOG_DIR/u01/backup/logs EXPDP_DIR/u01/backup/expdp/$(date %Y%m%d) DATE_TAG$(date %Y%m%d_%H%M%S) LEVEL${1:-0}这里有几个细节不能省。NLS_DATE_FORMAT必须设为yyyy-mm-dd hh24:mi:ss因为 RMAN 日志里的时间戳不设这个格式会很别扭排错时看不清楚归档的完成时间。BACKUP_BASE和EXPDP_DIR按天分开避免备份集堆积在同一个目录下也为后面crosscheck和删除策略提供清晰的路径来源。LEVEL参数允许你在命令行直接指定备份级别crontab 里调用时就不需要维护多个脚本了。3.2 全备与增量主体channel、format、tag 怎么配备份主体写成函数do_rman_backup用if [ $LEVEL 0 ]区分 level 0 和 level 1跑完通知外层函数做日志检查do_rman_backup() { mkdir -p ${BACKUP_BASE} ${LOG_DIR} rman target / log${LOG_DIR}/rman_${LEVEL}_${DATE_TAG}.log EOF run { allocate channel c1 device type disk format ${BACKUP_BASE}/b_%U.bak; allocate channel c2 device type disk format ${BACKUP_BASE}/b_%U.bak; backup incremental level ${LEVEL} database tag INC${LEVEL}_${DATE_TAG}; backup archivelog all not backed up 1 times delete input; backup current controlfile; release channel c1; release channel c2; } EOF if [ $? -ne 0 ]; then echo [ERROR] RMAN ${LEVEL} backup failed at $(date) ${LOG_DIR}/error_summary.log fi }逐行说参数。allocate channel c1 device type disk format ...%U.bak里的%U是 RMAN 自动生成的唯一字符串保证同一通道上的多个备份集文件名不冲突开两个 channel 时RMAN 会把备份集分片写到两个通道上并发读写能提升吞吐但通道数不要超过cpu_count否则反而争抢 IO。backup incremental level ${LEVEL} database tag INC...tag很重要恢复时用list backup of database tag INC0_...就能在众多备份里精确找到你要的那一个不用去翻时间戳。backup current controlfile这一行容易被新手忽略它的作用是在每次备份结束后强制单独备份一次控制文件。加上前面配置里的controlfile autobackup on控制文件实际上会被备份两次冗余换来的是恢复时更高的容错。3.3 归档日志删除策略delete input、not backed up 与 completed before 的区别归档删除策略是脚本里最容易翻车的部分热搜词里那条 rman delete archive,from,until,before区别 问的正是这里。先把我脚本里用的这行拆开讲backup archivelog all not backed up 1 times delete input;backup archivelog all表示把所有归档都纳入备份集not backed up 1 times表示只处理那些从未被备份过的归档delete input表示这些归档在进入备份集成功后立即删除。三个条件合在一起的效果是每天跑一次增量时只备份新增的归档备份成功后立刻释放磁盘空间不会误删尚未纳入备份集的归档。与之相对的是delete archivelog until time sysdate-3和delete archivelog completed before sysdate-3它们不关心归档有没有备份过只看时间。我在生产环境只在一种场景下用时间删除归档堆积已经跟不上备份节奏时作为兜底命令清理三天前的归档。但要注意until time、completed before、from ... until ...的区别completed before是按归档完成时间过滤until time在 delete 时实际也是按完成时间算两者差异很微妙from sequence ... until sequence则是按归档序号范围常在归档日志有断档时用来定向清理。日常脚本里不要混用我始终以not backed up 1 times delete input为主线时间删除只做兜底。3.4 数据泵导出把物理备份和逻辑备份放回同一个调度RMAN 物理备份解决的是整个库坏了能不能恢复的问题数据泵逻辑备份解决的是某张表被误删了能不能快速捞回来的问题。很多生产事故的恢复诉求其实只需要捞一张表用 RMAN 做表级恢复比较笨重所以这套脚本里我把 expdp 也纳入了统一调度do_expdp_backup() { mkdir -p ${EXPDP_DIR} expdp \/ as sysdba\ directoryDATA_PUMP_DIR \ dumpfileexpdp_${DATE_TAG}.dmp \ logfileexpdp_${DATE_TAG}.log \ schemasSCOTT,APP_USER \ parallel2 compressionALL \ clusterN }expdp / as sysdba的写法是为了避免把口令写在命令行里进程列表里不会暴露密码。schemasSCOTT,APP_USER是你想导出的业务模式列表按需调整别全库导出否则耗时长、文件大还容易卡在统计信息收集上。parallel2是导出并行度一般不超过 CPU 核数IO 紧张的系统建议降到 1compressionALL对 dump 文件启用压缩导出文件体积能小一半以上clusterN是 12c 以上版本必须加的否则 RAC 环境下 expdp 会尝试全集群调度容易报错。数据泵导出的安全性有一个细节expdp 导出期间如果表数据在变化导出的是读一致性的快照不会锁表但导出文件可能很大I/O 和 RMAN 备份叠加时要注意错峰。所以我一般把 RMAN 放在夜里 1 点expdp 放在凌晨 3 点错开 IO 峰值。4. 脚本部署与自动调度部署清单、crontab 与首次跑批检查4.1 部署前要确认的四个前置条件脚本不是拷过去就能跑部署前我强制自己过一遍以下四项检查缺一项后面都会在半夜里把你叫醒。第一ORACLE_SID和ORACLE_HOME是否正确特别是 RAC 环境两个实例的ORACLE_HOME路径可能不同。第二备份目录的属主和权限目录必须归oracle用户所有且空间足够我用df -h /u01/backup确认。第三数据库可登录性sqlplus / as sysdba不能需要密码否则 crontab 里跑不起来。第四归档模式确认把 2.1 那段 SQL 跑一遍输出里log_mode不是ARCHIVELOG就先别部署脚本。部署时我习惯先在命令行手动跑一次 level 0不要直接上 crontab。原因是手动跑能看到 RMAN 日志输出到终端第一时间发现路径错误、权限问题、归档异常这些在 crontab 里只会静默地写进日志文件等到第二天早上看到error_summary.log里挂着一条失败记录还得回头排查是哪一步出的问题。4.2 首次跑批与日志核查首次跑批建议用 nohup 方式在后台执行并观察日志尾部cd /u01/scripts nohup sh rman_backup.sh 0 /u01/backup/logs/nohup_$(date %Y%m%d).log 21 tail -f /u01/backup/logs/rman_0_$(date %Y%m%d_*).log脚本跑完后重点看三个地方。第一日志最后一行是否出现RMAN-03009或ORA-19506这说明备份过程中有文件级错误第二list backup summary;里是否出现了A 0或A 1的备份记录A 代表available0/1 代表 level第三检查v$rman_status的状态是否为COMPLETED。光看LOG_DIR里有没有生成日志文件不算验证我见过日志文件生成了但内容里全是错误的案例所以核查一定要看内容不能看存在性。4.3 crontab 编排周日全备、周一至周六增量、每天数据泵调度策略我采用周日全备周一至周六增量每天数据泵的组合这是单实例生产库性价比最高的方案。全备放周日凌晨 1 点增量放其他凌晨 1 点数据泵放凌晨 3 点既错峰又保证每天早上都有一个可用的逻辑备份# RMAN level 0 every Sunday at 01:00 0 1 * * 0 /u01/scripts/rman_backup.sh 0 /u01/backup/logs/cron.log 21 # RMAN level 1 from Monday to Saturday at 01:00 0 1 * * 1-6 /u01/scripts/rman_backup.sh 1 /u01/backup/logs/cron.log 21 # Data pump every day at 03:00 0 3 * * * /u01/scripts/rman_backup.sh exp /u01/backup/logs/cron.log 21crontab 里有个细节环境变量。crontab 默认 PATH 只有/usr/bin:/binOracle 的环境变量必须在脚本里自己 export这就是脚本头部那四行export的作用。另外日志双边记录cron.log只记录脚本启停具体 RMAN 日志在rman_*_*.log里两相对照才能定位问题。我每个月初还会额外加一条清理任务把超过 30 天的日志归档压缩防止日志目录本身把磁盘吃掉。5. RMAN 备份避坑实录磁盘满、备份集失效与恢复不到的高频问题5.1 归档堆积导致备份中途满盘ORA-19506 与删除策略失效现象RMAN 备份跑到 60% 左右报ORA-19506: failed to create sequential file紧接着磁盘空间不足备份失败。原因归档日志删除策略失效。最常见的是脚本里只写了backup archivelog all delete input但漏掉了not backed up 1 times这个条件。这会导致每次备份时RMAN 把包括昨天已经备份过的归档再备份一遍磁盘空间被重复备份消耗更隐蔽的是有些归档是在 RMAN 之外被其他工具归档的RMAN 元数据里没有记录delete input就永远不会删除它们。解决把归档备份统一改成backup archivelog all not backed up 1 times delete input;。如果当前磁盘已经被堆满先手工清理再用兜底命令delete noprompt archivelog all completed before sysdate-3;清掉三天前的归档让备份先跑起来。从那以后我把归档备份和delete绑死在一个语句里不再单独写删除命令。5.2 手动删备份文件导致备份集失效ORA-19809 与 crosscheck现象系统管理员清理磁盘时把/u01/backup下几天前的备份集文件删了但没动数据库。下一次增量备份正常list backup也还能看到被删的备份集记录恢复到该时间点时报ORA-19809: error in backup/restore file context找不到物理文件。原因备份集记录在控制文件或恢复目录里物理文件在文件系统里。RMAN 默认不会实时感知物理文件是否存在删除操作超出了 RMAN 的管理范围元数据和物理文件的对应关系就断了。这是文件系统和数据库管理职责分离导致的典型事故。解决禁止任何人在 RMAN 之外手动删除备份文件。清理动作必须通过delete obsolete或crosscheck来执行。我在脚本里加了一段每周自动执行的交叉校验rman target / EOF crosscheck backup; delete noprompt expired backup; crosscheck archivelog all; delete noprompt expired archivelog all; EOFcrosscheck的作用是让 RMAN 逐一核对物理文件是否存在不存在的就标记为EXPIRED随后delete expired把这些记录从控制文件里清掉。加了这段之后list backup里的记录永远和物理文件一致恢复时不会踩到记录在但文件不在的坑。5.3 没有 0 级基础就拉 1 级增量RMAN-20207 与基线管理现象新环境部署脚本后直接执行sh rman_backup.sh 1RM AN 报RMAN-20207: unable to find a base backup无法生成 level 1 增量。原因level 1 增量必须要有一个 level 0 基线存在RMAN 才能基于它计算变化块。很多人在测试环境里先跑了增量验证直接推到生产结果生产库没有 level 0 基线跑了个寂寞。解决首次部署时先强制跑一次 level 0。更稳妥的做法是在脚本里加一个基线判断每次跑 level 1 之前先查有没有最近的 level 0latest_base$(rman target / EOF | grep -c INC0 list backup of database tag like INC0% completed after sysdate-7; EOF ) if [ ${latest_base} -eq 0 ]; then echo No level 0 in last 7 days, force level 0 backup now. sh $0 0 exit $? fi这段逻辑的用意是如果最近 7 天内找不到任何 level 0 备份记录就自动降级为 level 0 全备保证增量链不中断。注意grep -c INC0是简单计数实际使用时可以更严格地匹配 completed 时间但思路一致——宁可多跑一次全备也别让增量备份在空基线上失败。5.4 不开控制文件自动备份控制文件与 SPFILE 全部丢失后的尴尬现象控制文件所在的磁盘损坏所有控制文件副本丢失同事试图用最近一次备份来恢复却发现 RMAN 连控制文件备份都没有restore controlfile找不到目标。原因脚本里只备份了数据文件和归档没单独备份控制文件也没开controlfile autobackup。控制文件一旦全部丢失RMAN 连从哪里开始恢复的元数据都没了。这个场景下数据文件再多备份也没用整个恢复流程直接瘫痪。解决脚本里的backup current controlfile配合配置里的configure controlfile autobackup on双保险恢复。更完整的做法是在备份脚本中单独构建一个控制文件恢复步骤。实际恢复时如果连控制文件备份都没有只能用dbms_backup_restore从数据文件头里重建控制文件那一刻你会深刻体会到什么叫备份做了但等于没做。所以我现在的习惯是每台库部署脚本后第一件事就是执行list backup of controlfile;确认控制文件备份确实存在而不是默认它一定存在。6. 恢复验证闭环用 restore validate 把备份盘成可交付资产备份脚本跑通不等于备份可用这个结论我是在一次真实的恢复演练里被教训出来的。那次的备份日志里连续一周都是COMPLETED但演练恢复时restore database直接报文件缺失——原因是某个数据文件从备份集里处于损坏状态备份过程却没感知。从那以后我每个月初都会在脚本里加一段强制执行的restore database validaterman target / EOF run { allocate channel v1 device type disk; allocate channel v2 device type disk; restore database validate; release channel v1; release channel v2; } EOFrestore validate不会真正恢复数据它只做两件事逐一读取备份集里的数据块校验块是否损坏、是否缺失顺带验证整条恢复链——从 level 0 基线到最近的 level 1 增量是否完整。它的输出里如果出现ORA-01547或ORA-01173说明备份集本身有问题必须立刻处理。注意restore validate是只读操作不会动数据库文件可以在业务低峰期放心跑。对于备份集级别的定向验证不想全库校验时可以指定备份集。先查备份集号再单独验证list backup of database summary; validate backupset 1234;validate backupset针对单个备份集做物理校验速度快很多适合日常抽检。我的验证套路是每月一次restore database validate跑全链路每周随机挑两个备份集做validate每次验证结果都追加到当月报告中。恢复演练脚本独立于备份脚本存放路径固定为/u01/scripts/rman_validate.sh这样任何接手的 DBA 都能在三分钟内跑完验证、拿到结论。备份的价值从来不在日志里那行 COMPLETED而在于你真正执行restore的那几分钟里它能不能把数据完整还给你。这套验证习惯我一直保持到现在每个月雷打不动跑一遍也是一名 DBA 给自己留的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表