Redo write触发的四种情况

本文详细介绍了Oracle数据库中LGWR(Log Writer)进程的工作原理。内容涵盖LGWR的触发时机,如定期检查、事务提交及DBWn写操作等场景;探讨了隐藏参数_log_io_size与_wait_for_sync的作用;并解释了group commit机制如何提高并发性能。
1、当LGWR空闲的时候,会每隔3秒检查一次是否有从redo buffer写入redelog中的数据,如果有,一个后台进程就会自动的执行将其写入
2、当有进程要从redo buffer中分配空间时,会先计算redo buffer中已经占用的空间,如果该空间大于_log_io_size这个参数值,并且此时的LGWR处于空闲状态,便会被激活执行后台写。_log_io_size的默认值是redo buffer大小的三分之一,从8.0开始,_log_io_size 的上限值是1M,和其他的hidden参数一样,如果没明确的设置,在X$KSPPSV视图中查出的值为0

3、当一个事物commit时,会产生一个commit标志在redo流中,在redo buffer中的log包括commit标志写入硬盘之前,这个事物是不可恢复的,因此在给用户返回类似‘Commit complete’之前,必须等待LGWR将redo buffer中写入硬盘,在commit后会激活LGWR并且sleeps on a log file sync wait with a timeout of 1 second。为了避免等待

可以将_wait_for_sync 参数设置成false,但是这样就不能保证已经commit的的事物实例失败时可以恢复。

_log_io_size 和  _wait_for_sync  都是隐藏参数,可以通过下面的sql查看其值

select  i.ksppinm name,  i.ksppdesc description,  cv.ksppstvl value,  
cv.ksppstdf isdefault,  decode(bitand(cv.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE') ismodified, 
decode(bitand(cv.ksppstvf,2),2,'TRUE','FALSE') isadjusted 
from  sys.x$ksppi i, 
sys.x$ksppcv cv  
where i.inst_id=userenv('Instance') and  
cv.inst_id=userenv('Instance') and 
i.indx=cv.indx and i.ksppinm like '/_%' escape '/'  order by  replace(i.ksppinm,'_','');

 


需要注意的是在回调语句中的commit并不会等待LWGR写入,例如存储过程中可能会有n个commit操作,但只有当药返回给用户执行结果的时候才会等待LWGR写入,即只会sync最后一个commit操作。

 

一个SGA变量(kcrfshsb, according to bug 182447)是用来确定最大的需要同步的log block号,当LGWR处于激活的状态过程中即正在像disk中写时,几个不同的实例事物执行commit操作,kcrfshsb 变量记录了需要同步的最高块号,这些commit会全部写入disk中在一次redo write中,称为group commit

 

4、当DBWn需要写入一个或多个块的high RBA ,并且high rba超出了on-disk RBA时,从8i开始DWBn将这些块放入延迟队列并且post LGWR来同步最高的RBA,但是不会等待,DBWn会继续执行其他的不需要延迟的写,在8i以前,DBWn会sleep发生log file sync wait。

<think> 我们正在讨论Oracle数据库中redo刷盘的实现方式。根据引用内容,redo刷盘是Oracle实现持久性和崩溃恢复的关键机制。下面我将基于引用内容详细解释redo刷盘的实现方式。 首先,根据引用[1],Oracle的Redo Log用于记录所有数据变更(如INSERT、UPDATE、DELETE、DDL等),确保已提交事务不会丢失。其核心原理是日志写先行(WAL),即先写Redo Log到磁盘,再写数据文件。 具体写入流程如下: 1. 事务执行时,生成Redo记录并写入Log Buffer(位于SGA中的一个循环缓冲区)。 2. LGWR(Log Writer)进程在满足以下条件之一时被触发: - 事务提交(commit) - Log Buffer满1/3 - 每隔3秒的超时(timeout) 3. LGWR将Log Buffer中的Redo记录写入当前的Online Redo Log文件(磁盘文件)。 4. 在写入磁盘时,Oracle会调用`fsync`(或类似的系统调用)强制将数据刷盘,确保数据持久化。 5. 刷盘完成后,通知用户事务完成(例如,在提交时,只有redo写入磁盘后才会返回提交成功)。 6. 后续由DBWR(Database Writer)进程将修改的数据块从Database Buffer Cache写入数据文件。 关于redo刷盘的关键点: - **强制刷盘机制**:LGWR在写入Online Redo Log文件时,会调用操作系统提供的同步写入(如`fsync`)来确保数据确实写入物理磁盘,而不仅仅是操作系统的文件系统缓存。这是保证事务持久性的关键。 - **Log Buffer的作用**:作为内存缓冲区,它减少了直接写磁盘的次数,提高了性能。当满足触发条件时,LGWR会将一批Redo记录写入磁盘,从而减少I/O次数。 - **Online Redo Log文件结构**:通常由多个日志组(每组可能包含多个成员用于冗余)组成,以循环方式使用。当一个日志组写满后,LGWR会切换到下一个日志组(称为日志切换),同时可能触发归档(如果数据库处于归档模式)。 此外,引用[2]提到可以进一步解析Redo的二进制格式或部署实践(如Data Guard),但用户当前问题聚焦于刷盘实现,因此我们集中在上述流程。 综上所述,Oracle redo刷盘的实现依赖于LGWR进程将Log Buffer中的记录写入磁盘Online Redo Log文件,并通过强制刷盘(如`fsync`)确保持久性。 §§相关问题§§ 1. LGWR进程在哪些具体条件下会被触发? 2. 为什么Oracle使用Log Buffer作为中间缓冲区? 3. 强制刷盘操作(如`fsync`)对性能有什么影响? 4. 在Oracle的不同版本中,redo刷盘机制有改进吗? 注意:根据引用,我们已经标注了引用位置[^1]。 </think> Oracle数据库中redo刷盘的实现是通过WAL(Write-Ahead Logging)机制保证事务持久性的核心过程,具体步骤如下: ### 1. **Redo记录生成** 当执行DML/DDL操作时: - 事务生成redo记录(包含变更详情) - 记录写入**Log Buffer**(SGA中的循环缓冲区) - 此时数据尚未写入数据文件[^1] ### 2. **LGWR进程触发条件** 后台进程LGWR在以下情况触发刷盘: - **事务提交**(COMMIT时强制刷盘) - **Log Buffer满1/3** - **超时机制**(默认3秒) - **DBWR写入前**(确保WAL原则)[^1] ### 3. **强制刷盘实现** 触发后执行关键操作: ```plaintext LGWR将Log Buffer内容 → 写入在线Redo Log文件 → 调用fsync()强制刷盘 ``` - 使用`fsync()`系统调用确保数据落盘(绕过OS缓存) - 磁盘I/O完成后通知用户事务提交成功 - 物理写入单位:**512字节磁盘扇区** ### 4. **持久化保障机制** - **原子写入**:单个磁盘扇区写入保证原子性 - **校验和**:每个redo块包含校验码(防止损坏) - **双写保护**:部分版本支持redo块双写(如Exadata) - **组提交优化**:合并多个事务的redo批量写入(减少I/O) ### 5. **与DBWR进程协作** 刷盘完成后: - DBWR异步将脏数据块写入数据文件 - 恢复保障:崩溃时通过redo前滚重做已提交事务[^1] $$ \text{事务安全} = \begin{cases} \text{COMMIT成功} & \iff \text{redo刷盘完成} \\ \text{崩溃恢复} & = \text{Redo前滚 + Undo回滚} \end{cases} $$ 此机制确保即使系统崩溃,已提交事务不会丢失(ACID中的D特性)[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值