oracle学习篇:六、重做(Redo)

重做(Redo)和撤销(Undo)是oracle的重要特性,用以保证事务的可恢复性和可撤销性。

6.1 Redo的作用

在数据库中,Redo的功能主要通过3个组件来实现:Redo Log Buffer、LGWR后台进程和Redo Log File(在归档模式下,Redo Log File最终会写出为归档日志文件)。

6.2 Redo的内容

改变向量:表示对数据库内某一个数据块所做的一次变更。

重做记录:通常由一组改变向量组成,是一个改变向量的集合,代表一个数据库的变更,构成数据库变更的最小恢复单位。

假定发出一个update语句:update emp set sal-4000 where empno=7788;

(1)检查empno=7788记录在buffer cache中是否存在,如果不存在则读取到buffer cache中;

(2)在回滚段空间的相应回滚段事务表上分配事务槽,这个操作需要记录redo信息;

(3)从回滚段读入或者在buffer cache中创建sal=3000的前镜像,这需要产生redo信息并记入redo log buffer;

(4)修改sal=4000,这是update的数据更新,需要记入redo log buffer;

(5)当用户提交时,会在redo log buffer 记录提交信息,并在回滚段标记该事务为非激活(inactive)。

6.3 产生多少redo

(1)在sql*plus中使用autotrace功能时

776 redo size

(2)通过v$mystat查询

记录当前session的统计信息

col name for a30

select a.name,ab.value from v$statname a,v$mystat b where a.statistic#=b.statistic# and a.name=‘redo size‘;

(3)通过v$sysstat查询

对于数据库全局redo的生成量,可以通过v$sysstat视图查询

col value for 9999999

select name,value from v$sysstat where name =‘redo size‘;

从该视图中得到的是自数据库实例启动以来的累计日志生成量,可以根据实例启动时间估算每天日志生成量。

select startup_time form v$instance;

归档日志数据量,v$archived_log,也可以反过来估计每日的数据库活动性及周期性,并决定空间分配等问题。

6.4 Redo写的触发条件

6.4.1 每3秒钟超时(Timeout)

LGWR执行写出操作,log file parallel write等待事件将会出现。

启用10046事件,从LGWR跟踪日志中可以清楚地观察到这些事件。

6.4.2 阈值达到

redo log buffer1/3 满

redo log buffer具有1MB脏数据

也就是LGWR将在min(1M,1/3 log buffer size)时触发,此时的log buffer size是以log block来衡量的。

log buffer设置为3MB?

6.4.3 用户提交

在事务返回成功标志前,必须等待LGWR写完成,进程通知LGWR写,并且以log file sync事件开始休眠,超时时间为1秒。

注意:在递归调用(recursive call)中的提交不需要同步redo知道需要返回相应给用户,因此递归调用仅需要同步返回给用户调用之前的最后一次commit操作的RBA。

存在一个SGA变量用以记录redo线程需要同步的log block number。如果多个提交在唤醒LGWR之前发生,此变量记录最高的log block number,在此之前的所有redo 都将被写入磁盘。这有时候被称为组提交(Group Commit)。

6.4.4 在DBWn写之前

6.5 Redo Log Buffer的大小设置

一般来说3MB是一个较为合理的调整开端,当log buffer space等待时间出现并且较为显著时,可以考虑增大log buffer以缩减竞争。

6.6 Commit做了什么

提交完成,意味着oracle已经将此时间点之前的redo写入了重做日志文件中。

6.7 日志的状态

select * from v$log;

最常见的状态有:current,active,inactive,unused

(1)current

当前、活动、正在被使用,是崩溃恢复必须的

(2)active

非当前、可能完成归档也可能没完成归档,在crash恢复时会被用到。

active状态意味着,检查点尚未完成,如果日志文件循环使用再次到达该文件,数据库将处于等待的停顿状态,此时在alert文件中,可以看到如下记录:

Thread 1 cannot allocate new log,sequence 7239

Checkpoint not complete

Current log# 5 seq# 7238 mem#0:/opt/oracle/oradata/hsmk/redo05.log

当这种问题出现时,可以从数据库内部通过v$session_wait来观察,该视图会显示数据库当前哪些session正处于这种等待。

Checkpoint not complete在数据库中体现为等待时间log file switch (checkpoint incomplete);

引起checkpoint imcomplete可能有以下多种原因:

①日志文件过小,切换过于频繁;

②日志组太少,不能满足正常事务量的需要;

③日志文件所在磁盘I/O存在瓶颈,导致写出缓慢;

④由于数据文件磁盘I/O瓶颈,DBWR写出过于缓慢;

⑤由于事务量巨大,DBWR负荷过高,不堪重负。

针对不同的原因,可以从不同角度着手解决问题:

①适当增加日志文件大小;

②适当增加日志组数;

③使用更快速磁盘存储日志文件(如采用更高转速磁盘:使用RAID10而不是RAID5等方式);

④改善磁盘I/O性能;

⑤使用多个DBWR进程或使用异步I/O等。

这是一类严重的等待,它意味着数据库不能再产生日志,所有数据库修改操作将全部挂起。

(3)inactive

inactive的日志是非活动日志,该日志在实例恢复时不再需要,但是在介质恢复时可能会用到。inactive状态的日志也可能没有归档。如果数据库启动在归档模式,在未完成归档之前,日志文件也不允许被覆盖,这时候活动进程会处于log file switch(archived needed)等待之中。

日志是否完成归档,可以根据v$log的archived字段进行判断。

这种情况通常是由数据库异常引起的,可能是因为I/O缓慢,也可能是因为事务量过大,在特殊情况下,有可能是因为日志损坏。可以通过检查警报日志文件发现问题所在。

(4)unused

unused是指该日志从未被写入,这类日志可能是刚被添加到数据库或者在resetlogs之后被重置。被使用后,该状态会被修改。

6.8 日志的块大小

512bytes

6.9 日志文件大小

一般来说,在实际生成环境中,把log switch的时间控制在半小时左右即可;

对于通常的操作系统来说,日志文件的最大大小为2GB,在非常繁忙的业务系统中,由于受限于日志大小,能将日志控制在10分钟左右就已经算不错了。

6.10 为什么热备期间产生的redo要比正常的多

这是因为在热备份期间,oracle为了解决split block的问题,需要在日志文件中记录修改的行所在的数据块的前镜像,而不仅仅是修改信息。

在热备状态下,对于变更的数据,oracle需要在日志中记录整个变化的数据块的前镜像。

select * from redo_size;

6.11 能否不生成redo

6.11.1 nologging对数据库的影响

nologging可以使得日志生成大幅降低,但是必要日志(比如对字典表的修改)仍会被记录。

可以使用nologging的环境非常有限,在一些操作中,可以增加nologging字句:

①创建索引或重建索引时;

②通过/*+append*/提示,使用直接路径批量insert操作或sql*loader直接路径加载数据;

③CTAS方式创建数据表时;

④大对象LOB的操作;

⑤一些alter table操作,如move、split等

创建视图便于查询redo日志

create or replace view redo_size

as

select value from v$mystat,v$statname where v$mystat.statistic#=v$statname.statistic# and v$statname.name=‘redo size‘;

6.11.2 disable_logging对于数据库的影响

除了以上常规操作之外,oracle还存在一个内部参数,可以使数据库关闭日志记录,从而实现某些特殊需要或测试目的,这个参数可以动态设置alter system set "_disable_logging"=true;

6.11.3 force logging模式

当使用dataguard作为数据库的备份或容灾高可用性手段时,通常日志就变得不可缺少,可以将数据库至于强制日志模式。在该模式下,所有操作都将记录日志。

6.12 redo故障的恢复

6.12.1 丢失非活动日志组的故障恢复

通过clear重建该日志组即可恢复

! rm /op/oracle/oradata/redo02.log

alter system switch logfile;

startup

atartup mount;

select * from v$log;

select * from v$logfile;

注意到,由于日志组2已经损失,在日志切换过程中,数据库crash,所以日志组3的状态变为invalidated,日志文件redo03.log的状态变为stale(stale通常出现在上一次操作失败后,在下一次成功操作后状态会恢复正常)

清除该日志组后即可启动数据库:

alter database clear logfile group 2;

如果数据库处于归档模式,并且该日志组未完成归档则需要强制清除:

alter database clear unarchived logfile group 2;

6.12.2 丢失活动或当前日志文件的恢复

oracle通过日志文件保证提交成功的数据不丢失,可是在故障中,用户可能损失了当前的日志文件。这又分为两种情况,数据库正常关闭还是异常关闭。

(1)在损失当前日志时,数据库正常关闭

在关闭数据库前,oracle会执行全面检查点,当前日志在实例恢复中可以不再需要。

(2)在损失当前日志时,数据库异常关闭

对于这种情况,通常需要从备份中恢复数据文件,通过应用归档日志文件向前推演,直到最后一个完好的日志文件,然后可以通过resetlogs启动数据库完成恢复,丢失的数据就是损坏的日志文件中的数据。

当数据库没有备份时,oracle提供了一种内部手段用于强制性数据库打开,忽略一致性等问题。在打开数据库之后,oralce建议导出exp数据, 然后重新建库,再导入imp数据,完成灾难恢复。

使用隐含参数强制启动数据库:

alter system set "_allow_resetlogs_corruption"= true spfile;

shutdown immediate;

startup mount;

recover database using backup controlfile until cancel;

alter database open resetlogs;

shutdown immediate;

startup

6.13 诊断案例一:通过clear日志恢复数据库

从日志看,数据库不能归档,归档路径错误

select * from v$archive_dest;

show parameter log_archive_dest;

由于多次归档不成功,导致数据库将归档日志标记未error,使得后续正常的日志同样无法归档。

select * from v$log;

可以看到在其他人进行的多次重启切换过程中,日志组2和日志组3的sequence#都已经增进,只有日志组1的sequence#仍然是202,由于日志组1并非current日志组,所以可以通过clear方式消除该日志内容,从而使该日志恢复正常状态。

alter database clear unarchived logfile group 1;

注意,由于该日志未归档,所以之前的热备份用于恢复时将不能跨越这个缺口,oracle建议重新全库备份,从警告日志中也可以看到提示。

后续工作是需要对数据库进行备份。

6.14 诊断案例二:日志组过度激活的诊断

问题描述:相应缓慢,应用请求已经无法返回

这时登陆数据库检查,发现redo日志组除current外都处于active状态

如果日志都处于active状态,那么显然dbwr的写已经无法跟上log switch触发的检查点。接下来检查以西dbwr的繁忙程度。

ps -ef|grep ora_

dbwr的进程号是2266,使用top命令观察一下:

top

可以看到2266号进程消耗的cpu不多,显然并不繁忙,那么瓶颈就很可能在IO上,使用iostat‘工具加检查io状况。”

iostat -xn 3

可以看到写速度(kw/s)只有500KB左右,而该磁盘通常写速度为为10MB/s,推测为磁盘发生了损坏。更换磁盘后,系统逐渐恢复正常。

第六章完

原文地址:https://www.cnblogs.com/myheart-new/p/11771573.html

时间: 2024-08-04 03:52:24

oracle学习篇:六、重做(Redo)的相关文章

oracle学习篇六:更新操作、事务处理

----------------1.数据库更新操作----------------------------- select * from tab;--查询表 drop table siebel_user;--删除表 --copy一份表结构create table myemp as select * from emp; select * from myemp; --插入记录insert into myemp(empno,ename,job,hiredate,sal,comm,deptno) val

oracle学习篇六:子查询

-- 1.查询比7654工资要高的员工 select * from emp where sal>(select sal from emp where empno=7654); ---2.查询最低工资的员工信息 select * from emp where sal=(select min(sal) from emp); ------------查询出,部门名称,部门员工数,部门平均工资,部门最低收入的人员姓名,和最高收入的人员 select d.dname,t1.c,t1.avgSal,t1.m

Oracle学习记录 六 又一本学习资料练习

学习过最简单的几种语句了,也安装过了几次数据库,本来在看那个高级编程的,但是还有一本入门的没看,就先看了再说, 多练习,熟悉掌握最基本的操作. 我以前登录的时候都是用conn回车,然后再输入密码,这个文档第一个就介绍了另一种登录方法. conn scott/xx 这样就直接登录了,/前是用户名,/后是密码 conn sys/xx as sysdba 这个就是用管理员登录 2. 然后是把刚才输入的sql保存成文件用.sql后缀 select * from emp; save /home/oracl

oracle学习篇:二、参数文件

2 参数文件 2.1 参数文件的获取 oracle的初始化参数可以通过查询v$parameter视图得到,在SQL*PLUS中,可以用过show parameter命令来显示某些参数的设置值. 2.2 参数文件 初始化参数文件:pfile 服务器参数文件:spfile 视图v$spparamter记录spfile参数的设置. 没啥好说的,直接学习一下案例分析. 2.3 诊断案例 问题描述:数据库在重新启动时无法正常启动,检查发现undo表空间丢失. 2.3.1 检查alert日志文件 警报日志文

Oracle学习笔记六 SQL常用函数

函数的分类 Oracle 提供一系列用于执行特定操作的函数 SQL 函数带有一个或多个参数并返回一个值 以下是SQL函数的分类: 单行函数对于从表中查询的每一行只返回一个值 可以出现在 SELECT 子句中和 WHERE 子句中 单行函数可以大致划分为: 1.日期函数 2.数字函数 3.字符函数 4.转换函数 5.其他函数 单行函数 日期函数 日期函数对日期值进行运算,并生成日期数据类型或数值类型的结果 日期函数包括: 1.ADD_MONTHS 2.MONTHS_BETWEEN 3.LAST_D

Oracle学习篇之SQL语句的优化

①在使用SELECT语句查询时,不要用"*"代替所有列名,因为这样的写法对Oracle系统来说会存在解析的动态问题.Oracle系统会通过查询数据字典来将"*"转换成表的所有列名,这自然会消耗系统时间. ②在子查询中,[NOT] IN子句将执行一个内部的排序与合并,无论在那种情况下,[NOT] IN都是最低效的,因为他对子查询中的表执行了一个全表遍历.为了提高效率,我们可以把它改写成外连接.NOT EXISTS 或者 EXISTS 子句. ③驱动表是指被最先访问的表

oracle学习篇七:同义词

Oracle数据库中提供了同义词管理的功能.Oracle同义词是数据库方案对象的一个别名,经常用于简化对象访问和提高对象访问的安全性. 在Oracle中对用户的管理是使用权限的方式来管理的,也就是说,如果我们想使用数据库,我们就必须得有权限,但是如果是别人将权限授予了我们,我们也是能对数据库进行操作的,但是我们必须要已授权的表的名称前键入该表所有者的名称,所以这就是比较麻烦的,遇到这种情况,我们该怎么办呢?创建个Oracle同义词吧!这样我们就可以直接使用同义词来使用表了. 1.同义词的概念Or

oracle学习篇十一:视图

视图是存储的查询定义. 1. 创建视图的语法如下: Create [OR REPLACE] [FORCE | NOFORCE] VIEW view_name[(alias,alias,...)] AS select_statement [WITH CHECK OPTION [CONSTRAINT constraint]] [WITH READ ONLY]; 其中: OR REPLACE 表示在该视图存在的话,将重新创建该视图. FORCE 使用此关键字,则无论基表是否存在,都将创建视图. NOF

oracle学习篇十:序列

序列:是用来生成唯一.连续的整数的数据库对象.序列通常用来自动生成主键或唯一键的值. 1. 创建序列语法如下: Create SEQUENCE sequence_name [START WITH integer] [INCREMENT BY integer] [MAXVALUE integer|NOMAXVALUE] [MINVALUE integer|NOMINVALUE] [CYCLE|NOCYCLE] [CACHE interger|NOCACHE]; 其中:START WITH: 是指定