Oracle本地部署 RMAN 备份脚本定时备份数据库


Oracle 本地部署 RMAN 备份脚本定时备份数据库

想必大家都听过一句话:备份是数据安全的最后一道防线。数据库是整个系统以及公司最重要的数据存放仓库,如果数据损坏丢失,将直接影响到公司业务以及财产的损失,Oracle RMAN 是官方推出最流行的在线热备方式,安全高效,部署简单。

DALL·E 2024-01-12 17.24.43 - A futuristic, technology-themed image emphasizing database data backup. The central focus is on a large, glowing digital sphere representing an Oracle

一、Oracle RMAN

在讲解如何使用 RMAN 进行备份之前,先了解下什么是 RMAN 备份吧!Recovery Manager (RMAN) 是一个 Oracle 数据库客户端,可以对数据库执行备份和恢复任务,并自动管理数据库备份策略,极大地简化了备份、还原和恢复数据库文件。

关于 Oracle RMAN 的入门使用,可以参考官方文档:**RMAN 入门** 写的很详细,我这里就不再赘述。

img

本文主要讲解如何在主机上部署 Oracle RMAN 备份脚本。

二、部署备份脚本

Oracle RMAN 在生产环境使用一般都是热备的方式,冷备需要关掉数据库才可以进行,生产环境一般是没有停机时间给你做备份的,所以冷备不太适合生产备份。热备的方式需要打开归档模式!

1、打开数据库归档模式

如果数据库已打开归档模式,执行 archive log list 可以看到以下结果:

归档模式查看

如果未打开归档模式,一般结果显示如下:

未归档

打开数据库归档模式需要重启数据库,完整步骤如下:

-- 设置归档日志路径
alter system set log_archive_dest_1='LOCATION=/archivelog';
-- 关闭数据库,重启至mount模式
shutdown immediate
startup mount
-- 开启归档模式
alter database archivelog;
-- 打开数据库
alter database open;
-- 检查归档模式是否打开
archive log list

重启数据库查看

如上图,数据库打开归档模式之后,接下来就可以开始部署 RMAN 脚本进行在线备份了。

由于打开归档模式后会源源不断的产生归档日志,所以建议部署一个定期删除归档的任务:

## oracle 用户下执行
SCRIPTSDIR=/home/oracle/scripts
mkdir -p ${SCRIPTSDIR}
{
echo '#!/bin/bash'
echo 'source ~/.bash_profile'
echo 'deltime=`date +"20%y%m%d%H%M%S"`'
echo "rman target / nocatalog msglog ${SCRIPTSDIR}/del_arch_\${deltime}.log<<EOF"
echo 'crosscheck archivelog all;'
echo "delete noprompt archivelog until time 'sysdate-7';"
echo "delete noprompt force archivelog until time 'SYSDATE-10';"
echo 'EOF'
} >>${SCRIPTSDIR}/del_arch.sh

chmod +x ${SCRIPTSDIR}/del_arch.sh

## root 用户下执行
SCRIPTSDIR=/home/oracle/scripts
{
echo "#00 02 * * * ${SCRIPTSDIR}/del_arch.sh"
} >>/var/spool/cron/oracle

2、本地备份脚本

Oracle RMAN 备份脚本的写法多种多样,根据不同的数据库环境可能有不同的写法。比如空间不够使用压缩备份,又比如数据库太大选择增量备份等等情况,我也不能全部照顾到大家的情况,所以这里就分享一个我比较常用的备份脚本,仅供参考!该脚本为增量备份脚本,分为 0 级和 1 级,周日 0 级全备,周一至周六 1 级备份。

首先需要在本地磁盘创建一个备份目录,需要有足够的磁盘空间:

## root 用户下执行
mkdir /backup
chown -R oracle:oinstall /backup
chmod -R 775 /backup

📢 注意: 以下脚本直接复制粘贴即可使用,只需注意修改对应的备份路径即可!

周日为 0 级备份脚本:

#!/bin/bash
source ~/.bash_profile
backtime=`date +"20%y%m%d%H%M%S"`
rman target / log=/backup/level0_backup_${backtime}.log<<EOF
run {
allocate channel c1 device type disk;
allocate channel c2 device type disk;
crosscheck backup;
crosscheck archivelog all;
sql"alter system archive log current";
delete noprompt expired backup;
delete noprompt obsolete device type disk;
backup incremental level 0 database include current controlfile format '/backup/backlv0_%d_%T_%t_%s_%p';
backup archivelog all DELETE INPUT format '/backup/arch_%d_%T_%t_%s_%p';
release channel c1;
release channel c2;
}
EOF

周一至周六为 1 级备份脚本内容:

#!/bin/bash
source ~/.bash_profile
backtime=`date +"20%y%m%d%H%M%S"`
rman target / log=/backup/level1_backup_${backtime}.log<<EOF
run {
allocate channel c1 device type disk;
allocate channel c2 device type disk;
crosscheck backup;
crosscheck archivelog all;
sql"alter system archive log current";
delete noprompt expired backup;
delete noprompt obsolete device type disk;
backup incremental level 1 database include current controlfile format '/backup/backlv1_%d_%T_%t_%s_%p';
backup archivelog all DELETE INPUT format '/backup/arch_%d_%T_%t_%s_%p';
release channel c1;
release channel c2;
}
EOF

📢 注意: 如果有多个实例,每个实例对应的脚本需要手动指定实例 export ORACLE_SID

脚本创建完之后,记得给脚本赋予可执行权限:

cd /home/oracle/scripts
chmod +x dbbackup_lv0.sh
chmod +x dbbackup_lv1.sh
ls -lrth

image-20240112170234925

3、定时任务

Oracle RMAN 本地备份脚本一般是与定时任务(crontab)配合使用,选择合适的时间段进行备份很重要,建议尽量挑选业务空闲或者负载较低的时间段进行备份。假设凌晨是业务空闲时段,部署定时任务:

## 在 root 用户下执行
su - root
echo "00 00 * * 0 /home/oracle/scripts/dbbackup_lv0.sh" >> /var/spool/cron/oracle
echo "00 00 * * 1,2,3,4,5,6 /home/oracle/scripts/dbbackup_lv1.sh" >> /var/spool/cron/oracle

crontab

关于 crontab 命令可以参考:Linux crontab 命令

这里设置好定时任务执行脚本,基本脚本部署就完成了。

三、备份脚本验证

一般备份脚本部署完之后,如果条件允许的情况下,我们都需要进行一次备份测试,来保证脚本的可执行性以及正确性,下面就简单的来做一次备份测试,验证一下咱们的备份脚本是否可以正常运行?

1、备份数据库

首先需要执行 0 级备份脚本进行数据库的备份,最好放在后台执行:

sh /home/oracle/scripts/dbbackup_lv0.sh &

测试备份功能

也可以连接到 RMAN 查看备份详细情况:

rman target /
list backup;

backup

也可以连接到数据库查询视图:

set line222
set pagesize1000
col status for a10
col input_type for a20
col INPUT_BYTES_DISPLAY for a10
col OUTPUT_BYTES_DISPLAY for a10
col TIME_TAKEN_DISPLAY for a10
select input_type,
status,
to_char(start_time,
'yyyy-mm-dd hh24:mi:ss'),
to_char(end_time,
'yyyy-mm-dd hh24:mi:ss'),
input_bytes_display,
output_bytes_display,
time_taken_display,
COMPRESSION_RATIO
from v$rman_backup_job_details
order by 3 desc;

image-20240112171459881

从上图也可以看出数据库备份的情况,分别有2次备份,一次是 18 号进行了全备,一次是 19 号进行了增量备份,备份状态,备份大小以及备份起始时间都可以看到。

接着再执行一次 1 级增量备份:

sh /home/oracle/scripts/dbbackup_lv1.sh &

由于没有什么数据更改,所以这次备份很快,再次查询一下备份情况:

1 级增量备份也成功,代表部署的备份脚本可以正常运行。

2、验证备份集

RMAN 也提供了备份集的验证功能,通过简单的几行命令即可验证备份是否可用:

restore validate database;
restore validate spfile;
restore validate controlfile;

验证备份集

验证备份

如上图所示,备份集验证均成功!

四、拓展

Windows 和 Linux 的脚本语法不太一样,这边也分享一下 Windows 的备份脚本,仅供参考!同样的分为 0 级和 1 级备份,Windows 部署定时任务的方式也有所区别。

0、 开启归档

-- 检查归档模式是否打开
archive log list
-- 关闭数据库,重启至mount模式
shutdown immediate
startup mount
-- 开启归档模式
alter database archivelog;
-- 打开数据库
alter database open;
-- 检查归档模式是否打开
archive log list

1、备份脚本

0 级备份脚本:

可执行 bat 文件:

新建文件和log目录

## 数据备份目录
D:\backup
## 日志目录
D:\backupscript\log
## 备份脚本
D:\backupscript\backupscriptV0.bat
D:\backupscript\backupscriptV1.bat
## 备份sql
D:\backupscript\backupscriptV0.sql
D:\backupscript\backupscriptV1.sql

@echo off
set "filename=backup_lv0_task_log_%date:~0,4%%date:~5,2%%date:~8,2%.log"
(
echo.
echo ====================backup %date% %time% =========================
echo.
D:\app\Administrator\product\11.2.0\dbhome_1\BIN\rman target / cmdfile=D:\backupscript\backupscriptV0.sql
echo.
echo ===================== finish %date% %time% =========================
echo.
)>>d:\backupscript\log\%filename% 2>&1<nul
exit

调用备份 SQL 文件:

run{
allocate channel c1 device type disk;
allocate channel c2 device type disk;
crosscheck backup;
crosscheck archivelog all;
sql"alter system archive log current";
delete noprompt expired backup;
delete noprompt obsolete device type disk;
backup incremental level 0 database include current controlfile format 'D:\backup\backlv0_%d_%T_%t_%s_%p';
backup archivelog all DELETE INPUT format 'D:\backup\arch_%d_%T_%t_%s_%p';
release channel c1;
release channel c2;
}

1 级备份脚本:

可执行 bat 文件:

@echo off
set "filename=backup_lv1_task_log_%date:~0,4%%date:~5,2%%date:~8,2%.log"
(
echo.
echo ====================backup %date% %time% =========================
echo.
D:\app\Administrator\product\11.2.0\dbhome_1\BIN\rman target / cmdfile=D:\backupscript\backupscriptV1.sql
echo.
echo ===================== finish %date% %time% =========================
echo.
)>>D:\backupscript\log\%filename% 2>&1<nul
exit

调用备份 SQL 文件:

run{
allocate channel c1 device type disk;
allocate channel c2 device type disk;
crosscheck backup;
crosscheck archivelog all;
sql"alter system archive log current";
delete noprompt expired backup;
delete noprompt obsolete device type disk;
backup incremental level 1 database include current controlfile format 'D:\backup\backlv1_%d_%T_%t_%s_%p';
backup archivelog all DELETE INPUT format 'D:\backup\arch_%d_%T_%t_%s_%p';
release channel c1;
release channel c2;
}

2、配置定时任务

Windows 的定时任务叫做 任务计划程序,需要在这里配置:

img

配置比较简单,下面跟着我简单走一遍流程!

首先,在空白处右键新增一个任务:

img

填好任务名称:

img

新建一个触发器,配置为每周日 0 点开始执行:

img

img

选择配置好的备份脚本可执行文件:

img

img

最后,直接点击确定完成创建:

img

可以看到任务已经布置完成:

img

Windows 配置本地 RMAN 备份跟 Linux 主机还是有点差异,但是本质是一样的。

删除Archive log

# 新建文件
D:\backupscript\delArchive.bat
D:\backupscript\delArchive.sql

delArchive.bat 脚本内容

@echo off
set "filename=archive_task_log_%date:~0,4%%date:~5,2%%date:~8,2%.log"
(
echo.
echo ====================backup %date% %time% =========================
echo.
D:\app\Administrator\product\11.2.0\dbhome_1\BIN\rman target / cmdfile=delArchive.sql
echo.
echo ===================== finish %date% %time% =========================
echo.
)>>D:\backupscript\log\%filename% 2>&1<nul
exit

delArchive.sql 脚本内容

run{
crosscheck archivelog all;
delete noprompt archivelog until time 'sysdate-7';
delete noprompt force archivelog until time 'SYSDATE-10';
}

控制文件删除恢复验证

# 删除控制文件
rm -rf /data/SPECTRA/control01.ctl
rm -rf /data/SPECTRA/control02.ctl

# 关闭数据库,将报错
shutdown immediate
# 强制关闭
shutdown abort
# startup 启动时会报错ORA-00205: error in identifying control file, check alert log for more info
startup

# 显示not mount
rman target /
# 进行恢复,不过中间过程比较痛苦,要一个个实验过来
restore controlfile from '/backup/data_SPECTRA_20240115_1158330783_96_1';

shutdown immediate;
startup mount;

# 继续用rman
restore database;
recover database;

# rman下启动数据库
sql 'alter database open resetlogs';

数据文件删除验证

# 删除控制文件
rm -rf /oradata/SPECTRA/datafile/o1_mf_testdb1_lt9nc80o_.dbf
rm -rf /oradata/SPECTRA/datafile/o1_mf_testdb_lt9mlwpz_.dbf

# 关闭数据库
shutdown immediate
#将报错ORA-01116: error in opening database file 2
#ORA-01110: data file 2: '/oradata/SPECTRA/datafile/o1_mf_testdb1_lt9nc80o_.dbf'
#ORA-27041: unable to open file
#Linux-x86_64 Error: 2: No such file or directory

# 强制关闭
shutdown abort
# startup 启动时会报错ORA-00205: error in identifying control file, check alert log for more info
startup

# 显示 mount
rman target /
# 恢复被删除的数据文件
restore database;

# 继续用rman进行数据库的信息恢复
recover database;


删除重做日志redolog验证

rm -rf /oradata/SPECTRA/redo*.log
shutdown immediate

# 将报错
#ORA-03113: end-of-file on communication channel
#Process ID: 22134
#Session ID: 17 Serial number: 8523
startup

# 再启动到mount状态
startup mount
# 报错RESETLOGS option only valid after an incomplete database recovery
alter database open resetlogs;

recover database until time '2024-01-15 15:25:00';



RMAN-06054 报错处理办法

主要原因是control文件和数据文件不一致引起的

最简单的办法就是把现有的control 文件也删除,然后从备份文件中恢复

# 删除这个控制文件,或者移动到其他地方
mv xxx xxxxx

# 数据库启动到nomount状态
sqlplus / as sysdba
startup nomount


rman target /
# 进行恢复,不过中间过程比较痛苦,要一个个实验过来
restore controlfile from '/backup/data_SPECTRA_20240115_1158330783_96_1';
# 启动到mount状态
startup mount
# 恢复被删除的数据文件
restore database;
# 继续用rman进行数据库的信息恢复
recover database;
# 开启数据库
alter database open;

删除spfile文件恢复

# 删除spfile文件
rm -rf /u01/app/oracle/product/19.3.0/db/dbs/spfilespectra.ora
# 或者移动文件
mv /u01/app/oracle/product/19.3.0/db/dbs/spfilespectra.ora /u01/app/oracle/product/19.3.0/db/dbs/spfilespectra.ora.bak

# rman 登陆
rman target /
# 强制启动到nomount
startup nomount force;

# 恢复spfile文件
restore spfile from '/u01/app/oracle/product/19.3.0/db/dbs/c-2905618578-20240115-06'


模拟坏块

  • 准备数据
-- 删除表空间和用户
drop user testDB cascade;
drop tablespace testDB including contents and datafiles;

-- 创建表空间
create tablespace testDB datafile '/oradata/SPECTRA/testDB.dbf' size 1G;
-- 创建用户
create user testDB identified by testDB default tablespace testDB;
grant dba to testDB;
-- 创建测试表
conn testDB/testDB
create table testDB as select * from dba_objects;
-- 创建表索引
create index idx_testDB_01 on testDB(object_id);

-- 查出包含行记录的数据块:
select distinct dbms_rowid.rowid_block_number(rowid) from testDB2.testDB2 order by 1;
select * from dba_extents where segment_name='TESTDB';

-- 在区间内,随机破坏 888、1030、1560 数据块的内容:
! dd if=/dev/zero of=/oradata/SPECTRA/testDB.dbf bs=8192 conv=notrunc seek=888 count=1
! dd if=/dev/zero of=/oradata/SPECTRA/testDB.dbf bs=8192 conv=notrunc seek=1030 count=1
! dd if=/dev/zero of=/oradata/SPECTRA/testDB.dbf bs=8192 conv=notrunc seek=1560 count=1

-- 清除buffer cache的内容
alter system flush buffer_cache;

-- 再次查询表 lucifer,此时查询已经报错,发现有坏块:

select * from testDB.testDB;
-- 遇到第一个坏块就会停止:
ERROR:
ORA-01578: ORACLE data block corrupted (file # 8, block # 888)
ORA-01110: data file 8: '/oradata/SPECTRA/testDB.dbf'

  • 坏块检查


    ## 检查对应的数据文件
    backup check logical validate datafile 8;

    -- 会列出坏块
    List of Datafiles
    =================
    File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
    ---- ------ -------------- ------------ --------------- ----------
    8 FAILED 0 129334 131072 3685503
    File Name: /oradata/SPECTRA/testDB.dbf
    Block Type Blocks Failing Blocks Processed
    ---------- -------------- ----------------
    Data 0 1398
    Index 0 166
    Other 3 174

    validate found one or more corrupt blocks
    See trace file /u01/app/oracle/diag/rdbms/spectra/spectra/trace/spectra_ora_22937.trc for details
    Finished backup at 22-JAN-24

    -- 结合 V$DATABASE_BLOCK_CORRUPTION 视图查看,更加方便:
    select * from V$DATABASE_BLOCK_CORRUPTION;

    FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO CON_ID
    ---------- ---------- ---------- ------------------ --------- ----------
    8 888 1 0 ALL ZERO 0
    8 1030 1 0 ALL ZERO 0
    8 1560 1 0 ALL ZERO 0

    -- 通过报错信息快照可以查找对应的坏表,依次填写数据文件ID8和坏块ID 888:
    SELECT tablespace_name, segment_type, owner, segment_name
    FROM dba_extents
    WHERE file_id = &fileid
    and &blockid between block_id AND block_id + blocks - 1;

    TABLESPACE_NAME SEGMENT_TYPE OWNER
    ------------------------------ ------------------ --------------------------------------------------------------------------------------------------------------------------------
    SEGMENT_NAME
    --------------------------------------------------------------------------------------------------------------------------------
    TESTDB2 TABLE TESTDB2
    TESTDB2


  • RMAN 恢复坏块

-- 使用备份来恢复坏块
blockrecover datafile 5 block 888,1030,1560;

Starting recover at 22-JAN-24
using channel ORA_DISK_1

channel ORA_DISK_1: restoring block(s)
channel ORA_DISK_1: specifying block(s) to restore from backup set
restoring blocks of datafile 00005
channel ORA_DISK_1: reading from backup piece /backup/backlv0_SPECTRA_20240122_1158940478_156_1
channel ORA_DISK_1: piece handle=/backup/backlv0_SPECTRA_20240122_1158940478_156_1 tag=TAG20240122T155438
channel ORA_DISK_1: restored block(s) from backup piece 1
channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01

starting media recovery
media recovery complete, elapsed time: 00:00:03

Finished recover at 22-JAN-24

记录删除恢复验证

  • 建立测试数据

## 创建用户
create user testDB identified by testDB;
grant dba to testDB;

## 用户登陆
sqlplus testDB/testDB@spectra

## 创建表空间
create tablespace testDB2 datafile ' /data/datafile/SPECTRA/testdb.dbf' size 10M autoextend off;

## 创建表
create table testDB(id number not null,name varchar2(20)) tablespace testDB;
## 插入数据
insert into testDB values(1,'test0');
insert into testDB values(2,'test1');
insert into testDB values(3,'test2');
commit;
## 查询数据
select * from testDB;

  • rman备份数据
su - oracle
rman target /
## 执行全库备份
run {
allocate channel c1 device type disk;
allocate channel c2 device type disk;
crosscheck backup;
crosscheck archivelog all;
sql"alter system switch logfile";
delete noprompt expired backup;
delete noprompt obsolete device type disk;
backup database include current controlfile format '/backup/data_%d_%T_%t_%s_%p';
backup archivelog all DELETE INPUT format '/backup/arch_%d_%T_%t_%s_%p';
release channel c1;
release channel c2;
}

## 查询rman备份结果
set line222
set pagesize1000
col status for a10
col input_type for a20
col INPUT_BYTES_DISPLAY for a10
col OUTPUT_BYTES_DISPLAY for a10
col TIME_TAKEN_DISPLAY for a10
select input_type,
status,
to_char(start_time,
'yyyy-mm-dd hh24:mi:ss'),
to_char(end_time,
'yyyy-mm-dd hh24:mi:ss'),
input_bytes_display,
output_bytes_display,
time_taken_display,
COMPRESSION_RATIO
from v$rman_backup_job_details
order by 3 desc;

  • 删除数据

## 用户登陆
sqlplus testDB/testDB@spectra
-- 删除前查询
select * from testDB;
-- 删除表 lucifer,最极端方式,确保无法通过回收站等方式恢复
drop table testDB purge;
-- 删除后再次查询报错
select * from testDB;

  • 单表恢复(19c以后)


    ## oracle 用户下执行 新建辅助目录
    mkdir -p /backup/tablereovery

    ## rman 下执行,在生产执行单表恢复,需要注意误删表的时间点,越精准数据丢失越少:
    rman target /
    RECOVER TABLE testDB.testDB
    UNTIL TIME "to_date('2024-01-15 14:33:00','yyyy-mm-dd hh24:mi:ss')"
    AUXILIARY DESTINATION '/backup/tablereovery/';


文章作者: JasonWen
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 JasonWen !
 上一篇
uptime kuma 超高颜值的服务在线监控工具,这个工具还真的是不错,可以把常用的一些端口加入的监控的范围,还有一堆的监控异常后推送的方式
2024-01-25
下一篇 
Screen-Studio:变革您的屏幕录制体验-高效、简易、专为macOS定制 Screen-Studio:变革您的屏幕录制体验-高效、简易、专为macOS定制
文章概述了Screen Studio的主要特点和优势,旨在向读者展示其作为macOS屏幕录制工具的价值。您可以根据您的博客风格和目标受众进行调整。
2024-01-14
  目录