1. 背景和原理介绍
1. 1 为什么需要备份恢复
考虑下面几个场景
1. 某个用户界面不久前误操作删除了一行数据并提交;
2. 开发人员误 truncate/drop 了一张表,过了几周才发现;
3. 管理器跑路前执行了 RM -RF *;
4. 服务器负载过大不能创建新的连接;
5. 数据块损坏导致数据丢失;
6. 发生了自然灾害导致服务器整个机房都没了。
我们不能避免数据丢失的情况发生,因为数据丢失是不可预料的,只能在它发生后,去尝试还原或修复数据。
针对上面的场景,有很多方法都能恢复数据或者使得服务可用。但是不同方法消耗的时间(也就是恢复时间目标)不同,用户当然期望越快恢复越好,所以对应最佳的方法如下
1. 使用快速恢复区闪回
2. 使用不完全恢复,恢复此表
3. 使用提前备份好的日志文件进行恢复
4. 使用 RAC 自动故障转移
5. 使用块介质恢复
6. 使用 DATA GUARD 主备切换 异地备份
我们在第四章用各种实例演示 1、2、3,且只讨论归档模式下的备份恢复,所用的工具是RMAN(recovery manager)恢复管理器.
1.2oracle 备份恢复工具简介
1.2.1RMAN
RMAN 恢复管理器是用于在表级别(Oracle Database 12c 新增)、数据文件、表空间和数据库级别上备份、还原和恢复数据库对象的主要工具。除了备份和恢复之外,RMAN 还有许多用途,包括把数据库克隆或复制到另一个位置。
1.2.2OSB
Oracle 安全备份(Oracle Secure Backup ,OSB)与 RMAN 一起提取 RMAN 备份,把它们复制到磁带设备或云存储中,以防止数据中心的灾难性故障而导致的数据丢失。OSB 还提供了 OS 级别上的 RMAN 扩展,来备份 Linux 服务器和任何附加的存储,例如网络附加存储(NAS)设备。
1.2.3 ORACLE DATA GUARD
确保企业数据的高可用性、数据保护和灾难恢复。在创建、维护和管理一个或多个同步备用数据库的同时避免灾难和数据损坏。
1.3 数据库的前滚和后滚
为什么数据库能实现异常恢复,大家可能会设想很多解决方案,比如每次提交前都在另一个地方备份一下,备份失败则提交失败,这样保证我总是能还原数据。数据库也是这样的机制, 我们后面进行探讨。
在一些数据丢失发生时,有些开发人员会问,我不是 commit 了吗,commit 了数据不是写磁盘里面了吗,数据还能丢?还有一些跑路的开发也会问,老板不良心,已经把表全都删了,回收站也清空了,这也恢复吗!其实配置得当,就算把库删了也能恢复。
为了解释这些问题,我会给你讲解很多前置知识,请慢慢往下看。
数据库有两个重要的后台进程 DBWn 和 LGWR,
当我们执行 UPDATE 的时候,前台进程会把数据写入 SGA 的块缓冲区中,并把内存数据和磁 盘数据做对比,不一样的标记为脏块,也就是说只改了内存没有改磁盘,内存是新数据,磁盘是过时的数据,同时改变向量也被写入重做日志缓存区
当我们执行 commit 的时候,会调用 LGWR 将重做日志缓冲区的数据刷入磁盘中的在线重做日志,仅此而已。
那么 DBWn 什么时候发挥作用呢?(也就是我们的修改在磁盘持久化保存)
1. 没有任何可用缓冲区
2. 脏缓冲区过多
3. 三秒超时
4. 检查点
这里我不去详细解释这四种情况对应什么,你只需要知道,持久化跟 COMMIT 没有任何关系
同时 LGWR 除了 COMMIT 转储日志,总共有下面几种情况起作用
1. Commit
2. 日志缓冲区占用超过 1/3
3. DBWn 将脏块写入磁盘前(所以也有三秒超时)
针对 commit.LGWR 能保证所有的日志都写入磁盘,是否把数据写入磁盘,则要看 DBWn 心情。这种情况是数据库要实现 RDBMS 以及性能要求,要实现数据安全,则每一笔 commit 更改都需要先写日志,保证能恢复,因为更改较多,那么 LGWR 就很繁忙,所以日志缓冲区非常小,因为每次 UPDATE,后面都有可能写入 commit,所以即使现在只执行了 UPDATE,为了让日志缓冲区空一点,也会提前将日志缓冲区写入重做日志文件,对应第二点和第三点。 而 DBWn 采用 LAZY 模式(为什么要采用懒写入大家可以思考一下,局域性原理,缓存被用 过一次很大可能被用第二次,数据被修改一次很大可能还会修改第二次),也就是能不刷就不刷,所以就存在这两类情况:
1. 执行了 UPDATE,未执行 COMMIT,数据未写入磁盘,日志未写入(正常)
2. 执行了 UPDATE,未执行 COMMIT,数据未写入磁盘,日志写入
3. 执行了 UPDATE,未执行 COMMIT,数据被写入了磁盘,日志一定被写入
4. 执行了 UPDATE,执行了 COMMIT,数据未被写入磁盘,日志一定被写入磁盘
5. 执行了 UPDATE,执行了 COMMIT,数据被写入磁盘,日志一定被写入磁盘(正常)
然后停电了,数据库直接崩溃,内存全被清空,如果没有恢复机制,使用人员就会看到,我明明点了保存,怎么还是没存上,开发人员执行了 UPDATE,又发现我没有提交怎么成功执行了修改。针对使用者而言,他想要的就是我 COMMIT 就保存,不 COMMIT 就不保存,红色部分对应不一致的情况
那么日志是怎么在恢复过程中起作用呢?
虽然我们在上面只标了 2 行,但是实例恢复都是一样的操作方式,也就是先前滚,在后滚
1. 没有日志,无法应用,这种情况不做任何操作。
2. 将在线重做日志的改变向量提取出来,应用到 SGA 块缓冲区上,有日志,应用,发现磁盘比内存旧,没有 commit,直接回滚内存上的块缓冲区操作
3. 将在线重做日志的改变向量提取出来,应用到 SGA 块缓冲区上,有日志,应用,没有commit,回滚块缓冲区,同时发现内存比磁盘旧,回滚磁盘
4. 将在线重做日志的改变向量提取出来,应用到 SGA 块缓冲区上,有日志,应用,有 commit, 磁盘比内存旧,将内存的数据刷到磁盘
5. 正常
1.4 在线重做日志
在线重做日志也叫联机重做日志,在 1.3 节里面我们看到了,假如没有联机重做日志,我们例子的 3 和 4 根本无法恢复,有人会说,能不能只要 commit 就写磁盘,那样数据库 IO 负载高,直接没法用了,可以自行搜索下面红框单词的含义
不过只要磁盘性能越来越好,内存越来越便宜,相信数据库底层架构也会做相应调整。
为了性能考虑,在线重做日志文件一般是设置多个重做日志 1,2,3。当日志文件 1 写满了, 而脏块还未刷,那么日志文件 1 就不能被重用覆盖写,所以就会切换日志组,往文件日志 2 写,日志 2 写完了,就往日志文件 3 写,3 写满了,此时时间过去了很久,那么日志文件 1 对应的脏块已经被刷到磁盘,所以可以安全的覆盖,于是就又可以往 1 写。如果 update 比 较频繁,脏块没来得及刷,日志则无法切换,产生等待事件 log file switch
我们查询一下当前的日志组
可以看到我有三个重做日志组,每个组内有两个成员,进行冗余备份,每个文件 200m 大小, 总共切换了 813 次,同时组 3 正在被写入日志文件。我们查看一下每个组成员
现在我们尝试主动切换日志组
alter system switch logfile;
结果如下
可以看到循环使用,从 3 变成了 1,由于 3 存在脏块未刷新,所以目前是 active。而 1 变成 current,后续 LGWR 就会往组 1 写。因为我的数据库不繁忙,结果等待了 5 分钟,期望可以看到组 3 刷新完成变成 INACTIVE,然而还是 ACTIVE,因此我们执行检查点刷新
alter system checkpoint;--完整检查点
可以看到马上就把脏块刷到磁盘了,这个检查点就是我们前面说的 DBWn 写入的检查点,当然检查点有很多,增量检查点、完整检查点、局部检查点,比如关闭数据库,脱机数据文件和表空间,截断表和备份都会触发检查点机制
增加日志组成员命令:
alter database add logfile member
'/usr/local/oracle19c/oradata/ORCL/redo01A.log' to group 1;
1.5 归档重做日志
前面说过,在线重做日志会覆写,开启归档后,会将在线重做日志复制到归档重做日志上,复制完成之后同时 inactive 才能被覆写,如果存储数据文件的介质遭到损坏,则可以使用归档重做日志进行恢复。比如这周六发生了数据丢失,我有周一的备份,就可以使用周一的备份进行还原,然后周一到周六的归档重做日志像快进一样,重放周一到周六的修改。
归档日志存放的路径可以设置在远程,这就是我们的异地备份的原理:DATA GUARD。
归档日志对应的进程是 ARCn(类别 DBWn,n 代表多路)
1.6 控制文件
数据库启动过程是 nomount->mount->open nomount
打开参数文件 spfile(二进制)或者 pfile(文本),分配 SGA 以及相应后台进程
而参数文件会记录控制文件的地址,我这里就不打印 pfile 的值了,参数文件的值可以用 parameter 查到,比如这样
SQL> show parameter control_files
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
control_files string
/usr/local/oracle19c/oradata/ORCL/control01.ctl,
/usr/local/oracle19c/oradata/ORCL/control02.ctl
在 mount 阶段,会打开控制文件,而控制文件记录了数据文件的名称和在线重做日志文件的位置。
最后 open 阶段则进行一致性检查,如果内存和磁盘数据一致,则打开,否则进行实例恢复。
详细作用:
1. 控制文件里面记录了数据库的物理结构,如数据文件,在线重做,归档重做的名称和位置
2. 检查点信息
3. 当前日志序号
4. 数据库名称
5. 时间戳
控制文件内部分为循环重用和非循环重用,循环重用的文件所在空间可以被覆盖,删除文件的时间有 control_file_record_keep_time 控制,标识循环重用记录最小保留的天数
控制文件一般会增长的很大,所以使用 catalog 更好,它不会覆盖文件。
如果使用控制文件进行备份,则需要设置 control_file_record_keep_time 比保留策略的时间更长。
点击加载更多