参考书籍: 循序渐进 Oracle 数据库管理优化与备份恢复
备份与恢复概述
在数据库环境中,常见的故障类型主要有:语句失败,用户进程失败,用户错误,实例失败,介质故障和网络故障。
- 实例失败:指数据库实例异常中断,如断电,异常错误导致 Crash,Shutdown abort 强制终止等。这类失败在下一次数据库重新启动后悔自动执行实例恢复(InstanceRecovery),通常能够自动顺利完成恢复启动数据库;
- 用户错误:指用户由于疏忽错误的 drop/truncate 掉数据表,或者误操作 delete/update 表中的数据并最终提交等。诸如此类的错误很常见,一旦这些错误出现,通常就需要 DBA 介入进行数据恢复或错误纠正;
- 介质故障:指当数据库对数据文件进行读写时出现问题,问题可能是由于硬件的故障,软件的 Bug,或者文件的意外删除等引发,介质故障是最为严重的数据库故障,也是 DBA 需要精心应付的主要问题;
备份方法
Oracle 的备份按照备份方式的不同可以分为两类:逻辑备份和物理备份。
逻辑备份:指通过逻辑导出对数据进行备份,逻辑备份的数据只能基于备份时刻进行数据转储,所以恢复时也只能恢复到备份时保存的数据。对于故障点和备份点之间的数据,逻辑备份是无能为力的,逻辑备份适合备份那些很少变化的数据表,当这些数据因误操作被损坏时,可以通过逻辑备份进行快速恢复。如果通过逻辑备份进行全库恢复,通常需要重建数据库,导入备份数据来完成,对于可用性要求很高的数据库,这种恢复的时间太长,通常不被采用。由于逻辑备份具有平台无关性,所以更为常见的是,逻辑备份被作为一个数据库迁移及移动的主要手动;
物理备份:指通过物理文件拷贝的方式对数据库进行备份,物理备份又可以分为冷备份和热备份。冷备份是指对数据库进行关闭后的拷贝备份,这样的备份具有一致和完整地时间点数据,恢复时只需要恢复所有文件就可以启动数据库;在生产系统中最为常见的备份方式是热备份,进行热备份的数据库需要运行在归档模式,热备份时不需要关闭数据库,从而能够保证系统的持续运行,在进行恢复时,通过备份的数据文件及归档日志等文件,数据库可以进行完全恢复,恢复可以一直进行到最后一个归档日志,如果联机日志存在,则恢复可以继续,实现无数据损失的
完全恢复
。当然,如果是为了恢复某些用户错误,热备份的恢复完全可以在某一个时间点上停止恢复,也就是不完全恢复
。
恢复原理
Oracle 数据库有一个重要的组成结构:重做日志(Redo Log)。重做日志用来记录数据库操作的必要信息,以便在发生故障时能够通过事务重演来恢复数据。Oracle 的数据恢复就依赖于重做日志文件(Redo Log File)以及由其衍生的归档日志文件(Archived Redo Log File)。
如果在恢复时我们拥有足够的归档日志和在线重做日志,那么通过恢复一个全备份,应用归档日志和重做日志,最终数据库就可以实现完全恢复,恢复后的数据库不会有任何数据损失。恢复流程如下:
恢复数据文件 –> 应用重做日志 –> 包含提交和未提交的数据 –> 应用回滚 –> 恢复数据库
如果恢复在应用日志完成前停止,则进行的就是一个不完全恢复。逐渐应用日志向前恢复的过程称为前滚(Roll Forward),前滚的过程实际上就是应用日志重演事务的过程,完成前滚后,数据文件将包含提交和未提交的数据,然后需要应用回滚数据,将未提交的事务回滚,这个过程称为 rolling back
或 transaction recovery
。
通常,完全恢复应用于那些由于硬件故障导致的数据库损失,在这种情况下需要最大可能的恢复数据;不完全恢复通常用于恢复用户错误。
在实际管理中,很多情况下进行的是不完全恢复,选择不完全恢复的可能原因很多,最常见的情况如下:
- 归档日志丢失。由于某个归档日志丢失,恢复只能执行到过去的某个时间点;
- 在线日志文件损坏。在线的日志文件损坏,则恢复只能停止在损坏的日志之前;
- 用户错误操作。用户错误的 drop/truncate 了数据表,恢复必须在这些动作发出前停止,以完成数据恢复。
不完全恢复主要有 4 种类型:基于时间的恢复(Time-based Recovery),基于放弃的恢复(Cancel-based Recovery),基于改变的恢复(Change-based Recovery),和基于日志序列的恢复(Log sequence recovery)。
数据库的运行模式
归档模式(Archivelog)和非归档模式(NoArchivelog)是 Oracle 数据库的两种运行方式,所谓归档是指对历史的 Redo Log 日志文件进行归档保存。在非归档模式下,Redo Log File 以覆盖的方式循环使用,在归档模式下,日志文件被覆盖之前必须已经被复制归档,保留的归档日志将为 Oracle 提供强大的故障恢复能力。
在命令行,可以通过命令 archive log list
获取当前数据库的归档状态。例如:
1 | SQL> archive log list; |
- Database log mode: 数据库日志模式;
- Automatic archival: 自动存档;
- Archive destination: 存档目的地;
- Oldest online log sequence: 最早的联机存档日志序列;
- Current log sequence: 当前日志序列
运行在归档模式下,数据库需要额外的空间存放归档日志,而且写出归档日志会为数据库带来性能负担,但是归档模式可以为数据库带来强大的可恢复性,所以生产数据库通常都应该运行在归档模式下,当然归档模式应该和相应的备份策略相结合,只有归档模式没有相应的备份策略只会带来麻烦。很多用户由于缺乏必要的监控和备份策略,在归档模式下由于归档空间耗尽而导致数据库故障。
修改数据库运行模式
更改数据库的归档模式需要重新启动数据库,在 mount 模式下修改,以下是步骤说明:
- 修改必要的初始化参数;
- 以 immediate 方式关闭数据库;
- 启动实例到 mount 状态;
- 更改运行模式并打开数据库;
以下简单介绍如何启用和关闭数据库的归档模式
修改初始化参数。和归档相关的几个主要参数如下:
- log_archive_start: 用于定义是否启动自动归档,Oracle 10g 这个参数废弃;
- log_archive_format: 用于定义归档文件格式,可以采用缺省值;
- log_archive_dest: 用于定义归档文件路径,与 log_archive_dest_n 参数不兼容;
- log_archive_dest_n: Oracle 允许定义多个归档路径,一般可以使用 log_archive_dest_1 参数即可。
如果数据库使用的是 pfile 文件,则可以直接修改,如果使用的是 spfile 文件,则可以通过命令行修改:
1
2
3
4
5
6
7SQL> show parameter spfile;
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
spfile string /u01/app/oracle/product/11.2.0/dbs/spfileorcl.ora
SQL> alter system set log_archive_dest_1='location=/data/backup/oracle/archive';
System altered.注意,备份文件存放路径的目录必须要先创建好,并且 Oracle 用户要有写入权限。在 Oracle 10g 之前,更改数据库为归档模式,还有一个重要的初始化参数需要修改,这个参数就是 log_archive_start,用于限制 Oracle 可否自动归档,如果该参数设置为 FALSE,数据库即使在归档模式下也不会自动归档,当日志写满后,Oracle 会等待用户进行手工处理,如果所有日志全部写满,那么数据库的所有 DML 操作将会全部挂起,数据库将会经历服务中断。而且这个参数的默认值是 False。从 Oracle 10g 开始,这个参数失去作用,即使该参数为 False,数据库在归档模式下也会自动归档。
关闭数据库。以
shutdown normal
或者shutdown immediate
方式关闭数据库1
2
3
4SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.启动数据库到
mount
状态1
2
3
4
5
6
7
8
9SQL> startup mount;
ORACLE instance started.
Total System Global Area 1720328192 bytes
Fixed Size 2214056 bytes
Variable Size 1006634840 bytes
Database Buffers 704643072 bytes
Redo Buffers 6836224 bytes
Database mounted.启用或停止归档模式,如果要启用归档模式,此处使用
alter database archivelog
名令1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18SQL> alter database archivelog;
Database altered.
SQL> alter database open;
Database altered.
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /data/backup/oracle/archive
Oldest online log sequence 3
Next log sequence to archive 5
Current log sequence 5
SQL> show parameter log_archive_start;
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
log_archive_start boolean FALSE如果需要停止归档模式,此处使用
alter database noarchivelog
命令1
2SQL> alter database noarchivelog;
SQL> alter database open;
闪回恢复区 Flash Recovery Area
从 Oracle 10g 开始,Oracle 数据库引入了一个闪回恢复区(Flash Recovery Area)的概念,所谓闪回区是指用于存储和恢复相关的一系列备份文件的磁盘空间。通过这个闪回区,Oracle 可以简化用户的备份行为和备份管理,进一步地,Oracle 可以对备份文件执行大量的自动维护工作。
在创建数据库时可以设置闪回区,闪回恢复区可以指定为文件系统上的一个目录,也可以是一个 ASM 磁盘组,闪回区的大小由 db_recovery_file_dest_size
参数指定,路径由 db_recovery_file_dest
参数指定。这两个参数都是动态参数,可以动态地进行修改。
1 | SQL> show parameter db_recover; |
以下几类主要文件可以在闪回区中存放:
- 控制文件;
- 回档的日志文件;
- 闪回日志;
- 控制文件和 SPFILE 自动备份;
- RMAN 备份集;
- 数据文件拷贝.
设置归档日志存放在闪回区,可以使用以下命令
1 | SQL> alter system set log_archive_dest_1 = 'LOCATION=USE_DB_RECOVERY_FILE_DEST'; |
注意,log_archive_dest_1 与 log_archive_dest 和 LOG_ARCHIVE_DUPLEX_DEST 参数不兼容,如果设置了 log_archive_dest 参数,需要先将其清空
1 | SQL> alter system set log_archive_dest='location=/data/backup/oracle/archive'; |
闪回区的一个优势是 Oracle 会执行自动的空间维护,过期的文件或备份可以自动被删除以释放空间。在闪回恢复区中的空间使用超过 85% 的时候,数据库将会向 alert 文件中写入告警信息;当超过 97% 的时候,将会写入严重告警信息;当闪回恢复区空间不够的时候,则数据库将会挂起,日志中会记录类似如下信息:
1 | ORA-19815: WRANING: db_recovery_file_dest_size of xxxxxxxxxx bytes is 100.00% used. and has 0 remaining bytes available。 |
再接下来的告警信息中将会提示一系列的归档错误信息。
注意这里的一个词 reclaim
,这个词的主要词义是 “回收”。Oracle 用了回收在这里,意思就是已经没有空间可以回收以满足归档的空间需求了;这也意味着如果闪回区中存在过期的备份或者归档,数据库是可以自动删除这些文件以回收空间的。
当 Oracle 在 reclaim 空间时,可能看到如下类似的信息:
可以看到,Oracle 自动的删除了过期的备份和归档日志文件。
使用闪回区,要注意闪回区的利用率,一旦空间耗尽,那么数据库将陷于停顿状态,如果真的遇到 ORA-19815 错误,那么就可以在警告日志文件中看到 Oracle 建议的详细解决方案.
1 | ORA-19815: WARNING: db_recovery_file_dest_size of xxxxxxxxxx bytes is 100.00% used. and has 0 remaining bytes available. |
很多人习惯通过手工清除文件的方式释放空间,但是数据库无法得知这个空间释放。所以即使删除了文件,连接数据库查询相关视图(v$recovery_file_dest 视图),空间仍然得不到释放(可以参考 v$recovery_file_dest.used 字段)。
删除归档日志文件,正确的做法应该是使用 RMAN 登录数据库进行 crosscheck,再删除过期的备份,空间才能得到释放。常用的命令如下:
1 | SQL> crosscheck archivelog all; |
这样删除之后空间才能得以释放
按照 Oracle 的提示,可以通过以下命令,将闪回区的内容备份到第三方介质,也同样可以解决这个问题
1 | SQL> backup recovery area; |
另外,如果闪回区存储的空间可以扩展,则可以动态修改初始化参数 db_recovery_file_dest_size,增加闪回区空间,在设置这个参数时,Oracle 并不会实时检查存储的剩余空间,所以在解决紧急故障时,可以先修改这个参数恢复数据库服务再来研究空间释放的问题。
1 | SQL> show parameter recovery; |
经过空间扩展,数据库即可恢复正常。有了闪回恢复区之后,在执行 RMAN 备份操作时,如果不指定路径,缺省的备份将存储在闪回区中;
1 | $ rman target / |
逻辑备份与恢复
使用 EXP 进行逻辑备份
导入/导出(IMP/EXP)是 Oracle 最古老的两个命令行工具,通过导出(EXP)工具可以将 Oracle 数据库中的数据提取出来,在恢复时可以将数据导入(IMP)进行恢复。但需要注意的是,使用 EXP 备份的数据进行全库恢复时,需要重新创建数据库,导入备份的数据,恢复的过程可能极为漫长。
逻辑导出(EXP)的使用方法在命令行通过 exp -help
命令可以直接得到。关于 EXP 命令的说明如下:
通过直接输入 EXP 命令和你的
username/password
,导出操作将提示你输入参数,例如1
EXP SCOTT/TIGER
通过输入跟有各种参数的 EXP 命令来控制导出的运行方式。要指定参数,可以使用关键字,格式如下:
1
2
3EXP KEYWORD=value
# 或者
EXP KEYWORD=(value1,value2,...,valueN)例如:
1
2
3EXP SCOTT/TIGER GRANTS=Y TABLES=(EMP,DEPT,MGR)
# 或者
EXP SCOTT/TIGER GRANTS=Y TABLES=(T1:P1,T2:P2) # 如果 T1 是分区表注意: USERID(username/password)必须是命令行中的第一个参数。
以下是 EXP 帮助信息中所有可用的关键字以及说明
Keyword 说明(默认值) USERID 用户名/密码 BUFFER 数据缓冲区大小 FILE 输出文件(EXPDAT.DMP) COMPRESS 导入到一个区(Y) GRANTS 导出权限(Y) INDEXES 导出索引(Y) DIRECT 直接路径(N) LOG 屏幕输出的日志文件 ROWS 导出数据(Y) CONSISTENT 交叉表的一致性(N) FULL 导出整个文件(N) OWNER 所有者用户名列表 TABLES 表名列表 RECORDLENGTH IO 记录的长度 INCTYPE 增量导出类型 RECORD 跟踪增量导出(Y) TRIGGERS 导出触发器(Y) STATISTICS 分析对象(ESTIMATE) PARFILE 参数文件名 CONSTRAINTS 导出的约束条件 OBJECT_CONSISTENT 只在对象导出期间设置为只读的事务处理(N) FEEDBACK 每 x 行显示进度(0) FILESIZE 每个转储文件的最大大小 FLASHBACK_SCN 用于将会话快照设置回以前状态的 SCN FLASHBACK_TIME 用于获取最接近指定时间的 SCN 的时间 QUERY 用于导出表的子集的 select 子句 RESUMABLE 遇到与空格相关的错误时挂起(N) RESUMABLE_NAME 用于标识可恢复语句的文本字符串 RESUMABLE_TIMEOUT RESUMABLE 的等待时间 TTS_FULL_CHECK 对 TTS 执行完整或部分相关性检查 TABLESPACES 要导出的表空间列表 TRANSPORT_TABLESPACE 导出可传输的表空间元数据(N) TEMPLATE 调用 IAS 模式导出的模板名
帮助部分详细介绍了 EXP 的使用方法,以上帮助内容来自 Oracle 11gR2。接下来简要介绍几个关于 EXP 的注意事项及特殊用法。
EXP 导出的注意事项及特殊用法
EXP 导出与字符集
导出客户端的字符集设置会影响导出数据,所以应该设置导出客户端字符集和数据库相一致。在 Windows 的命令行可以如下设置:
1 | C:\> set nls_lang=AMERICAN_AMERICA.AL32UTF8 |
在 Linux/Unix 上 Bash 下通常可以如下设置:
1 | export NLS_LANG=AMERICAN_AMERICA.AL32UTF8 |
数据库端使用的字符集可以通过如下查询获得
1 | SQL> select * from NLS_DATABASE_PARAMETERS where parameter='NLS_CHARACTERSET'; |
带查询字句的部分导出
从 Oracle 8i 开始,EXP 工具支持使用查询字句对特定表的部分数据执行导出,这个功能是通过 EXP 的 query 参数来实现的,在使用过程中可能最常见的错误是:
1 | LRM-00112: multiple values not allowed for parameter 'query' |
这通常是因为 QUERY 字句包含特殊字符导致的,由于特殊字符在命令行通常需要转义,所以导出的语法结构通常于与众不同。
在 Windows 上,通常可以使用如下方式指定 QUERY 字句:
1 | exp ... query='where col=1000' |
例如:
1 | C:\> exp eygle/eygle@dana file=test.dmp tables=tquery query=\"where object_id < 1000\" |
在 Linux/UNIX 的 Bash 下,通常可以如下方式指定 query 参数:
1 | exp ... query=\"where col \< 1000\" |
例如:
1 | exp eygle/eygle file=test.dmp tables=tquery query=\"where object_id \< 1000\" |
参数文件的使用
对于类似以上的复杂处理,可以通过参数文件 PARFILE 来指定一个参数文件,具体的参数写在参数文件中,这样就可以避免复杂的转义等操作:
1 | # cat parfile.lst |
使用通配符进行模糊导出
有时候我们希望按条件导出部分表,EXP 工具支持模糊查找,通配符可以在 tables 参数中使用。例如
1 | exp eygle/eygle tables=e% file=a.dmp |
这样,以字符 e 开头的表都被导出了。
按日期区分文件名称的导出
很多时候,在导出备份时,我们希望在文件名中加入日期变量,以区分不同日期的导出文件,也可以防止覆盖。在导出文件名中引入时间有很多种不同的做法,本文主要介绍以下两种方法:
通过数据库查询获取日期,通过数据库查询可以获得需要的日期格式。
在 Windows 上可以编写两个文件用于完成备份,一个是可执行的批处理文件,名称为 startbak.bat,内容如下
1
2
3echo off
set oracle_sid=eygle
sqlplus eygle/eygle @expbydt.sql第二个文件是 expbydt.sql 脚本,内容如下
1
2
3
4column today new_val dt
select to_char( sysdate, 'ddmmyyyy') today from dual;
host exp userid=eygle/eygle file=exp_eygle_&dt..dmp log=exp_eygle_&dt..log
exit准备好这两个文件之后,就可以通过命令行运行 startbak.bat 来执行逻辑备份了。
在 Linux/UNIX 系统上的 Bash 环境下可以做类似的操作,如下
1
2
3
4
5
6
7
8
9
10
11# cat startbak.sh
#!/bin/bash
set oracle_sid=orcl
sqlplus scott/tiger @expbydt.sql
# cat expbydt.sql
column today new_val dt
select to_char( sysdate, 'ddmmyyyy' ) today from dual;
host exp userid=scott/tiger file=exp_scott_&dt..dmp log=exp_scott_&dt..log
exit准备好了这两个文件之后,就可以通过命令行运行 startbak.sh 来执行逻辑备份了。
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
65
66
67# sh startbak.sh
SQL*Plus: Release 11.2.0.1.0 Production on Sat Apr 24 22:00:15 2021
Copyright (c) 1982, 2009, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining,
Oracle Database Vault and Real Application Testing options
TODAY
------------------------
24042021
Export: Release 11.2.0.1.0 - Production on Sat Apr 24 22:00:15 2021
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining,
Oracle Database Vault and Real Application Testing option
Export done in UTF8 character set and AL16UTF16 NCHAR character set
server uses AL32UTF8 character set (possible charset conversion)
. exporting pre-schema procedural objects and actions
. exporting foreign function library names for user SCOTT
. exporting PUBLIC type synonyms
. exporting private type synonyms
. exporting object type definitions for user SCOTT
About to export SCOTT's objects ...
. exporting database links
. exporting sequence numbers
. exporting cluster definitions
. about to export SCOTT's tables via Conventional Path ...
. . exporting table DEPT 4 rows exported
EXP-00091: Exporting questionable statistics.
EXP-00091: Exporting questionable statistics.
. . exporting table EMP 14 rows exported
EXP-00091: Exporting questionable statistics.
EXP-00091: Exporting questionable statistics.
. . exporting table SALGRADE 5 rows exported
EXP-00091: Exporting questionable statistics.
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting referential integrity constraints
. exporting triggers
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting materialized views
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting statistics
Export terminated successfully with warnings.
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining,
Oracle Database Vault and Real Application Testing options检查一下导出后的文件名称,如果备份计划无误,就可以通过定时任务来定时执行这个任务了。
通过操作系统获取日期,时间变量也可以直接通过操作系统获得,在 Windows 上,我们可以通过如下命令获得
1
c:\> echo %date:~0.10%
当然,在 Windows 上的时间格式和区域设置有关,如果以上命令输出的日期格式存在问题,那么可以调整一下区域设置的日期。可以通过一个名为 expbdt.bat 的批处理文件来执行导出操作:
1
2
3echo off
set oracle_sid=eygle
exp userid=eygle/eygle full=y file=d:\backup\exp_eygle_%date:~0.10%.dmp log=d:\backup\exp_eygle_%date:~0.10%.log在 Linux/UNIX 的系统上,时间的定义就显得更为简单:
1
exp scott/tiger file=scott_`date +%Y%M%d`
导出的文件名如下
1
2
3# ll
total 32
-rw-r--r-- 1 oracle oinstall 24576 Apr 24 22:19 scott_20211924.dmp