Chinaunix首页 | 论坛 | 博客
  • 博客访问: 251035
  • 博文数量: 59
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 698
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-19 21:17
文章分类

全部博文(59)

文章存档

2009年(14)

2008年(45)

我的朋友

分类: Oracle

2008-12-14 21:31:00

oracle instance recovery
 
1、oracle有两大很重要的文件,那就是控制文件和联机日志文件。
oracle的一旦有一个控制文件丢失那么数据库就立即当机。而同时如果有一组数据库的联机日志不可用,因为日志是循环使用的,一旦日志切换到到使用该日志组时,数据库就当机了。因此日志文件和控制文件一般需要镜像,控制文件需要多个拷贝,同时放入多块磁盘。日志文件,建议每个日志组至少两个成员,每个成员放在不同的磁盘上。
 
2、instance的恢复
instance的恢复是需要smon完成的,smon完成数据文件、控制文件和重做日志文件的同步。instance恢复的时间是由应用的脏缓冲区块个数决定,而脏缓冲区块个数的最大值是由检查点确定。如下参数是控制检查点的:
fast_start_mttr_target:instance恢复的最大时间(单位为秒)
log_checkpoint_timeout:指定发出检查点的最大时间间隔(单位为秒)
log_checkpoint_inteval:指定发出检查点的重做日志块间隔(单位为os块个数)
log_checkpoint_timeout,log_checkpoint_inteval是为了与早期版本的兼容而保留的。一般建议使用fast_start_mttr_target控制恢复时间,
10gR2开始提供自动的数据库检查点,设置为0就是使用自动调整的数据库检查点。其实具体检查点的进度可以通过v$instance_recovery视图查看。
v$instance_recovery视图下有三个字段:
actual_redo_blks:instance恢复实际需要的重做块个数
target_redo_blks:instance恢复最多需要应用的重做的块数
estimated_mttr:instance恢复预计的时间
而instance实际恢复时间主要是由redo和undo时间确定的,因此也需要调整redo和undo的时间。
 
调整redo时间:
默认恢复redo是由smon进程完成的。
recovery_parallelism用来标识用来参与实例恢复的进程数,当该值为0或者1时,表示只采用一个进程来进行恢复。
如果该参数值大于1表示可以采用多个slave进程去进行恢复。
 
调整undo时间
默认恢复undo也是由smon进程完成的。
为了减低undo恢复时间,fast_start_parallel_rollback可以控制恢复undo的slave进程的个数。
该参数值含义:
false:禁止并行回滚功能
low:2*cpu个slave进程数
high:4*cpu个slave进程数
可以通过v$fast_start_servers查看undo操作的进程信息。
select pid,status,undoblockdone from v$fast_start_servers;
状态字段idle表示空闲,而recovering表示正在恢复。
也可以通过视图v$fast_start_transactions视图undoblockdone表示已经恢复的数据块数,而undoblocktotal表述需要回退的总的块数。
 
3、查看实例恢复的undo进度的方法:
现创建一张表
create table test(a number,b number);
begin
   for i in 1..1000000 loop
       insert into test valus (i,i+1);
   end loop;
end;
在执行上述语句后,不提交,我们另外开启一个会话,shutdown abort,然后再执行startup的时候,就会发现,smon在执行实例恢复。
通过查询v$fast_start_transactions可以观察实例恢复的进度,undoblockdone字段在不断的增加,而同时硬盘在疯狂的读写,当undoblockdone字段等于undoblocktotal字段时,undo恢复完成。
 
4、关于实例恢复的一个经典疑问
因为log buffer写进redo log file的条件并不是commit,那么这样将导致部分未提交的事务已经写进联机日志文件,同时dbwr写数据的条件也不是commit,那么也可能部分未提交的事务的改变已经写进数据文件了。而日志切换的条件是该日志内的相关信息已经全部写到数据文件了,那么该日志就可以覆盖。因为smon的实例恢复是从最后一次的checkpoint开始向后恢复的,那么checkpoint之前的日志是不会读取了,有可能
部分日志想读也读不了,那么这批事务是如何恢复的呢?
    道理其实很简单的,虽然redo不再了,或者是读不到了,但是undo如果事务不提交的话,是不会被覆盖的,未提交的undo永远存在,并且这些相关的回滚段是活动的。那么smon可以根据这些回滚段来对事务进行回滚。
    如果数据库Crash,重新启动,很久远以前的未提交事务并不在Redo的恢复序列中。但是未提交事务一定在回滚段事务表上存在,并且State=10,为活动事务,数据库启动后,会将这些活动事务标记为dead,而dead事务在v$transaction表中是无法查询的,这需要一张内部的表x$表才能查询,本文下面我会继续提及。dead事务将由smon慢慢回滚。因为回滚操作是在数据库打开后才进行回滚的,那么可能有进程去读
取这部分没有提交的数据,那么这时发现dead事务还没有提交,那么smon会主动回滚。
   
   总之,未提交的事务一定有可用的回滚段存在。
   比如:
   1)update事务1更新了block 1
   2)回滚段1记录了block1的前镜像
   3)checkpoint
   4)update事务2更新了block2
   5)回滚段2记录了block2的前镜像
   6)instance crash
   现在重启数据库。
   1)因为和该日志相关的脏数据还没有被checkpoint,因此redo中的信息还是可以读取,根据redo重新构建block2
   2)根据redo重新构建回滚段2
   3)database open
   4)SMON用回滚段2的数据回滚block2
   5)SMON用回滚段1的数据回滚block1
  最后一步也可能是在另外一个select检索到block1或者block2的时候,发现这两个block的数据都是未提交的,此时再回滚block1和block2
 
  因此这个疑问现在可以解决了。因为只要有相应的回滚数据存在,无论什么时候oracle都可以找到一致的数据,oracle只需要知道这个事务
是提交了的还是没提交了的,而这点在block header ITL中有记录。
  其实我现在又产生了一个疑问,回滚段如果被覆盖了,那么该事务肯定是被提交了。既然回滚段在,那么为什么需要根据日志去重构回滚段呢?
 
5、实例回滚案例模拟
1)查询日志状态
> select status,sequence# from v$log;
STATUS            SEQUENCE#                                                    
---------------- ----------                                                    
CURRENT                  82                                                    
INACTIVE                 80                                                    
INACTIVE                 81   
2)创建用户,表,执行PLSQL
> create user antiper identified by antiper default tablespace users temporary tablespace temp;
用户已创建。
> grant connect,resource,dba to antiper;
> conn
已连接。
>
begin
   for i in 1..100000 loop
       insert into test values (i,i);
   end loop;
end;
/
没有提交
3)sys另外开启会话,查询日志,强制关闭数据库,启动模拟instance recovery
查询日志状态
select status,sequence# from v$log;
STATUS            SEQUENCE#                                                    
---------------- ----------                                                    
INACTIVE                 85                                                    
ACTIVE                   86                                                    
CURRENT                  87  
 
shutdown abort
startup
 
说明:
日志从序号82切换到了87,而日志只有3组,说明只要日志中的相关信息全部写到数据文件,即只要日志相关的检查点完成了,就可以进行日志切换,而和日志中redo/undo相关的事务是否提交无关。
 
第一次查询相关系统表:
select pid,state,undoblocksdone from v$fast_start_servers;
PID STATE UNDOBLOCKSDONE
-------------------
16 RECOVERING 189
select distinct KTUXECFL,count(*) from x$ktuxe group by KTUXECFL;
KTUXECFL COUNT(*)
------------
SCO|COL 3
DEAD 1
NONE 574
select t.STATE,t.UNDOBLOCKSDONE,t.UNDOBLOCKSTOTAL from v$fast_start_transactions  t
STATE UNDOBLOCKSDONE UNDOBLOCKSTOTAL
-------------------------------------
RECOVERING 283 814
 
再次查询时上述相同的三条SQL:
select distinct KTUXECFL,count(*) from x$ktuxe group by KTUXECFL;
KTUXECFL COUNT(*)
------------
SCO|COL 3
NONE 574
再次查询时,无进程为dead的记录
select t.STATE,t.UNDOBLOCKSDONE,t.UNDOBLOCKSTOTAL from v$fast_start_transactions  t
STATE UNDOBLOCKSDONE UNDOBLOCKSTOTAL
-------------------------------------
RECOVERING 566 814
说明每次查询时,恢复的undoblock是不断的增加的。
select pid,state,undoblocksdone from v$fast_start_servers;
PID STATE UNDOBLOCKSDONE
-------------------
再次查询无记录,应该是恢复进程已经完成,因为我查询的时候进程还是在做恢复。

6、PMON
在实例当掉的时候,重启数据库需要SMON恢复那些没有提交的时候,而如果在实例打开情况下,如果意外中断而没有提交的事务需要pmon去释放相应的资源。
引出两个问题:如何加快pmon释放资源呢?如何去处理状态为killed的进程?呵呵!
阅读(2960) | 评论(0) | 转发(0) |
0

上一篇:让oracle快速启动起来

下一篇:北京出差

给主人留下些什么吧!~~