Skip to content

1.谈谈对redo的理解

作为这一系列文章的开头,我想说一些问题,它们是我在学习oracle到这一步入门时候所积累的一些经验。
任何的技术学习都有一个目的,学习oracle也一样。在学习到redo的时候你又是怎么样的目的?这里不妨我提出几个问题,作为思考的方向。

1.redo 日志是什么?
2.redo 有何作用?
3.redo 直接有关的进程有哪些?
4.redo 和内存中的哪块区域有关?
5.redo 相关的字典或者视图有哪些,redo记录了哪类信息?
6.redolog的结构是怎么样的?
7.在数据库中怎么统计一个事务的相关redo量?

关于redo重做日志的概念可以参考《concepts》里1.1.3.3部分的介绍.我这里将对redo作主要特征以及运行原理的理解阐述。

一:redo的介绍

redo日志它记录了对database的所有变更操作的记录,这些在数据库中的变更操作记录叫做重做日志条目(redo entry).redo日志主要应用在Recover(实例恢复以及介质恢复),dataguard,goldengate,stream等恢复以及数据同步的环境中。

二:redo entry有3个主要特性:

2.1.在实例中,一个变更操作在数据库加载在buffercache之前或者实际的block操作之前就已经在log buffer中生成相关的redo entry(重做日志条目)
2.2.在将变更的块写入datafile之前,相关事务的redo entry必须先由lgwr进程写入到redo logfile中
2.3.当一个事务提交的时候,logbuffer中的redo entry写入到redo log file

(这里原理涉及到了checkpoint以及增量checkpoint的机制,在这个系列的checkpoint中将会结合oracle在redo设计上为了保护crash方面作详细解说.)
三:redo entry的生成:
3.1:10g中的写redo log buffer的步骤(10g的新特性,即IMU,in memory undo)

1. 通过获得在private memory中的配对的内存结构,开始事务。配对的内存结构一个是从x$ktifp(即in memory undo pool,负责undo变化矢量),一个是从x$kcrfstrand(即private redo,负责forward变化矢量)。
2.标记每个受影响的block为“has private redo”(但是不改变block)
3.将每个undo变化矢量写入被选中的in memory undo pool
4.将每个redo变化矢量写入被选中的private redo thread
5.通过将上述的2个内存结构串联到一个redo change记录中,事务完成(shared pool)。
6.将redo change记录拷贝到redo中,并且将change apply到block上。

1

3.2:10g之前版本的redo record 生成步骤
  datablock在block header分配ITL。
  生成undo的change vector(PGA)
  生成data的change vector(pga)
  将undo的redo vector和data的redo vector合并成一条change record。
  获得redo copy的latch
  获得redo allocation的latch
  将change record写入到log buffer中
  应用undo的change vector
  应用data的change vector
2

四 Redo log的存储相关
1. redo logfile是存储在系统中的,它使用的redo 块大小取决于操作系统的块大小。通常是512bytes,存储格式取决于操作系统和数据库版本。
2. 每一个redo logfile包含了日志文件头,重做日志条目
3. redo logfile的重做日志条目是顺序写的方式
一个redo logfile的基础结构如下图:
3

ORA-09925的几种可能情况

ORA-09925 Unable to create audit trail file
这个错误通过提示可以知道是无法在adump指定的目录上创建相关的文件,这个错误无非以下这几种情况:

1.adump指定的目录不存在(路径错误)
2.adump指定目录oracle用户无权限写
3.adump指定的目录使用率100%
4.adump指定的目录offline

这类错误是比较简单的,光看报错的提示就可以知道。

有些同学认为是审计开启导致了,其实这个和审计参数的设置是没有任何关系的。(可以参考ocp教材10-10 force audit)
在oracle中默认存在一个强制性审计,它会审计一些特定的操作,比如数据库启动或者关闭。它和审计参数的设置没有关系。

12.实例恢复,介质恢复,崩溃恢复的原理理解

OCP教材 042 – 02章

1、media recovery是需要利用以前的备份来进行恢复的,而INSTANCE RECOVERY是不需要的。

2、media recovery通常发生在数据库的数据文件之类发生损坏,需要利用以前的备份来进行的恢复,需要人工处理;

而INSTANCE恢复则是发生在实例不正常关闭情况下的恢复,是INSTANCE自己来的,不需要人工干预的。

Media Recovery 概念:

如果发生数据文件丢失或破坏,就需要用备份和归档日志来进行恢复,这种恢复操作就叫作介质恢复(Media Recovery),这种恢复操作需要有备份、归档日志、联机日志一起才能完成,并分成完全恢复和不完全恢复两种情况。

Instance Recovery概念:

如果实例被SHUTDOWN ABORT方法强行关闭,或者因为断电等事故发生故障。数据文件、控制文件、联机日志都没有丢失,这时数据库再次启动时,要利用联机日志的内容进行恢复,这种恢复就是实例恢复(Instance Recovery)。

Instance Recovery主要包括3个阶段:

1)根据联机日志内容进行ROLLOVER;

2)打开数据库,提供服务;

3)SMON或用户进程进行ROLLBACK。

Crash Recovery:

到了RAC环境下,同样也有Media Recovery和Instance Recovery,并且RAC还有Crash Recovery。

简单地说,Instance Recovery是指所有的实例都发生Crash后进行的Recovery,从发生地点来看,这种Recovery发生在故障实例上,是故障实例重新启动时执行的Recovery。

而Crash Recovery是指某个实例发生了Crash后在其他实例上进行的Recovery。这里最重要的区别是发生地点不是在故障节点,而是在某个健康节点。这种Recovery有一个特殊要求:在健康节点执行Crash Recovery时,必须要保证故障节点不能再对共享数据进行操作,也就是要对故障节点进行IO隔离(IO Fencing),这是由CSS服务来保证的。

在单实例环境下,Crash Recovery和Instance Recovery没有区别。只有在RAC这种多实例环境下,这两个名词的区别才能体现出来。

说明:对于Crash Recovery最重要的是,必须保证在执行Crash Recovery时,故障节点被IO Fencing。

Crash/Instance Recovery与Media Recovery的本质区别在于:

Crash/Instance Recovery针对需要恢复的实例从增量检查点(incremental checkpoint)开始apply redo应用重做日志。由于日志覆盖的先提条件是完成相关日志的logfile switch checkpoint,且从定义上说归档日志总是落后于实例的检查点,所以对于crash/instance recovery崩溃或实例恢复总是只需要访问读取在线的重做日志(online redo logfile)。

介质恢复Media Recovery从旧数据文件的检查点开始apply redo引用重做日志,这些旧的数据文件可能来源于备份。 介质恢复情况下需要用到归档重做日志,因此RMAN或DBA(用户管理的备份)也需要将备份相关的归档日志还原出来。

Crash/Instance Recovery总是保证仅当所有的持久重做数据被应用之后才算恢复完成。 在Oracle保证所有已提交的事务都已经被包含恢复的情况下,才认为崩溃实例完成了恢复工作。

相反,介质恢复有不完全恢复(incomplete recovery)和部分恢复(partial recovery)的提法,以实现恢复数据库(db)到某个时间点的一致性。

Crash/Instance Recovery与Media Recovery的相同点在于:

Crash/Instance Recovery与Media Recovery都是传统的前滚恢复方式(rolling forward),原理上都是对持久redo log数据的重演。 不管是Crash/Instance Recovery还是Media Recovery的前滚,都需要继之以事务回滚以便回滚未提交的事务,虽然前滚完成后数据库即可以打开而不用等回滚完成,但是仅在回滚完成的时候我们认为数据库是真正一致的。

浅谈Oracle的恢复机制以及各种恢复手段(更新中)

一直都要把redo,undo在recovery中是怎么协调作用的东西写下来,一直都往后推拖,到了现在稍微有了点时间,也就顺便把这一系列的东西做了一个整理.
我这些文章中对log的dump操作请参考文章
How to Dump Redo Log File Information

大概会有3个大系列,分为如下部分:

1.谈谈redo

1.1.谈谈redo以及Imu的理解
1.2.什么是redo Records
1.3.理解redo log file header,redo block header and redo record header
1.4.什么是change vectors
1.5.理解Row and Index Operations
1.6.理解Direct Loads以及Nologging 在redo中的展现
1.7.理解审计与Redo之间的关系
1.8.理解附加日志内幕
(www.ludatou.com)

2:谈谈undo机制

2.1.理解undo的作用
2.2.理解事务与undo的关系
2.3.理解XID
2.4.理解UBA
2.5.理解UNDO CHAIN实现机制
2.6.理解延迟块清除
2.7.关于ora-01555的处理
(www.ludatou.com)

 

3.谈谈检查点机制

3.1.

4.谈谈控制文件

4.1理解控制文件的作用
4.2理解bootstrap

5.谈谈恢复原理以及特殊恢复技术

5.1.概念:实例恢复,介质恢复,崩溃恢复的概念
13.深入理解recovery的实现机制:Page Fix、写日志优先、Checkpoint
(www.ludatou.com)
5.1.1无法启动故障根本原因的定位案例
5.2.ora 00600 [2662]处理
5.3.ora 00600 [4097]一例
5.4.ora 00600 [4193]处理
—-BBED处理
5.5.数据文件头损坏恢复
5.6.控制文件损坏恢复
5.7.系统表空间损坏恢复

 

 

简便的数据刷选安全控制方式以及不可避免的ORA-01039错误

对于一些使用Oracle或者其他数据库(比如mysql,sql server,sybase,db2等)的企业或者单位,在涉及到一些数据交涉(可能是多级单位之间的数据交换获取)过程中,经常会碰到一些不愿意被对方看到的数据,那么这个时候就需要相关的表数据做刷选再传递给对方,刷选的方式有不少,比如dmg,rls,ols(rls的升级版),fgac,身份验证,role control等,更甚者会用dbv,这些都是oracle在安全方面所做的支持,每一种的设置都有自己优势和弊端,到这里你一定以为我会选择上面的一种方式来实现,哈哈~这里我要介绍的是采用view或者synonym的方式来控制,这里以Oracle数据库中来限制数据访问的最简单的方式为例子,在Oracle中如果相关数据规模不大,或者相关的业务执行频率可控,而且要做dml的限制,那么首先建议就是是采用view或者synonym,反之如果对dml有要求,要么在评估性能的基础上选择上面介绍的方式外,还有物化视图的方式。

具体如下:
我们先提出需求,用户a要求查询b下的b.t1表的关于id=100的数据,但是b用户不希望a用户在能看到t1表下id=100之外的数据,采用view的方式就会如下:

一.测试环境搭建:

create user a identified by ludatoua;
create user b identified by ludatoub;
grant resource,connect to ludatoua;
grant resource,connect to lidatoub;
grant select any dictionary to ludatoua; — 必须要的
grant select any dictionary to ludatoub; — 必须要的
grant select on v_$session to ludatoua;
grant select on v_$sesstat to ludatoua;
grant select on v_$statname to ludatoua;

B用户下:

create table t1 as select * from all_objects; –记得要现有权限
alter table t1 add rn number;
update t1 set rn=300;
update t1 set rn=100 where rownum < 5;

二.根据要求,通过建立view的方式刷选数据:

B用户下:

create view xh$t1 as select * from t1 where id=100;
grant select on ludatoub.xh$t1 to ludatoua;

A用户下操作:
view方式限制:

create synonym t1 for ludatoub.xh$t1;

synonym方式限制:

create synonym t1 for ludatoub.xh$t1;

到了这里我们要做简单的数据刷选(数据访问限制)已经完成了,但是有一个问题是不能被忽略的,ORA – 01039错误(在看执行计划的时候产生导致无法对这个view的执行计划进行观测), insufficient privileges on underlying objects of the view。错误的解释是相关对象的视图没有权限去访问定义的基表。这样的错误很多人都碰到过,但是都没有一个很好的解决方案,网上公布得最多的是grant select any dictionary to user的方式来解决,但是这个只能解决本身用户的,在我们这的情况下(在ludatoua)用户下,这种方式就起不到左右了。有兴趣的同学可以使用10053或者46去看在看执行计划时候到哪一步报错没权限,我这里就不列出了。
问题的原因在与view的嵌套视图的基础对象,ludatoua用户是没有对ludatoub下的对象select权限的,因为我们需要控制ludatoua不能直接访问ludatoub的t1表。在我们的案例中就是ludatoua用户无法对ludatoub的t1对象进行select才导致了这里看执行计划时候报错 ORA – 01039。这是采用view方式的一种弊端,所以时候时候还是需要权衡(个人使用过程影响不大,调优都是对view的刷选语句进行)。

这里在选择view或者synonym方式的时候就需要对view相关sql的性能进行了解,避免糟糕的性能对业务引起的不必要的影响,而view方式的调优都都在view本身这层。