服务于区块链开拓者

www.zhidnet.com

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

参见;http://www.ixora.com.au/notes/redo_write_triggers.htm http://www.eygle.com/archives/2005/02/redoaeoeio.html There are four conditions that cause LGWR to perform a redo write. When LGWR is idle, it sleeps on an rdbms ipc message wait with a timeout of 3 seconds (as does DBWn). If this sleep times out and LGWR finds that there is some redo available to write, a background write is performed spontaneously. Whenever a process allocates space in the log buffer, the number of used log buffer blocks is calculated. If the number of used blocks is greater than or equal to the number of blocks specified by the _log_io_size parameter, and if LGWR is not already active, then LGWR is posted to perform a background write. The default value for _log_io_size is 1/3 of the log buffer expressed in log blocks, with an upper bound equivalent to 1 Mb from release 8.0. As with many other hidden parameters, unless set explicitly, the _log_io_size parameter reports as zero in X$KSPPSV. When a transaction commits, it generates a commit marker in the redo stream. However, the transaction is not recoverable until the log block containing that commit marker has been flushed to disk. So, before the process finishing the transaction can return a response to the user, it must wait for LGWR to flush that log block to disk. The process therefore posts LGWR and then sleeps on a log file sync wait with a timeout of 1 second. For completeness, the _wait_for_sync parameter can be set to FALSE to avoid waiting for redo to be synced, but doing so voids any guarantee of recoverability for committed transactions upon instance failure. Note that commits within recursive calls (such as procedural code execute calls) do not need to sync their redo until a response is about to be returned to the user. Therefore recursive calls just sync the commit RBA of their most recent COMMIT upon return to the user call. They do not sync each commit. An SGA variable (kcrfshsb, according to bug 182447) is used to communicate the log block number up to which the redo thread needs to be synced. If several commits occur in distinct transactions before LGWR wakes up, this variable records the highest log block number that needs to be synced, and the commit markers are all flushed to disk in a single redo write. This is sometimes called a group commit. When DBWn needs to write one or more blocks for which the high RBA is beyond LGWR's on-disk RBA, from Oracle 8i, it places those blocks into its deferred write queue and posts LGWR to sync the highest high RBA, but it does not wait. Instead DBWn continues to process other writes that do not need to be deferred. Prior to release 8i, DBWn used to sleep on a log file sync wait in this case. 为了保证用户可以快速提交,LGWR的写出必须非常活跃,我们非常熟悉的LGWR写触发条件就有4条。

1. 每3秒超时(Timeout)

当LGWR处于空闲状态时,它依赖于rdbms ipc message等待,处于休眠状态,直到3秒超时时间到。如果LGWR发现有redo需要写出,那么LGWR将执行写出操作,log file parallel write等待事件将会出现。

2. 阀值达到

我们在各种文档上经常会看到的2个触发日志写的条件是: ·Redo Log Buffer 1/3满; ·Redo Log Bufrer 具有1MB脏数据。 这两个都是限制条件,在触发时是协同生效的。我们知道,只要有进程(Process)在Log Buffer中分配和使用空间,已经使用的Log Buffer的数量将被计算。如果使用的块的数量大于或等于一个隐含参数_log_io_size的设置,那么将会触发LGWR写操作。 如果此时LGWR未处于活动状态,那么LGWR将被通知去执行后台写操作。 缺省的_log_io_size等于1/3 Log Buffer大小,上限值为1MB,此参数在X$KSPPSV([K]ernel [S]ervice [P]arameter Component [S]ystem [V]alues)中显示的0值,意为缺省值。 也就是,LGWR将在Min(1M,1/3 log buffer size)时触发。注意此处的Log Buffer Size是以Log Block来衡量的。此值通常为512 bytes GetHidPar.sql select x.ksppinm name, y.ksppstvl value, y.ksppstdf isdefault, decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE') ismod, decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE') isadj from sys.x$ksppi x, sys.x$ksppcv y where x.inst_id = userenv('Instance') and y.inst_id = userenv('Instance') and x.indx = y.indx and x.ksppinm like '%_&par%' order by translate(x.ksppinm, ' _', ' ') sys@NEI> @GetHidPar Enter value for par: log_io_size old 4: AND x.ksppinm LIKE '%&par%' new 4: AND x.ksppinm LIKE '%log_io_size%' NAME VALUE DESCRIB ------------------------------ -------------------- ------------------------------------------------------------ _log_io_size 0 automatically initiate log write if this many redo blocks in buffer 一个常见的经验推荐是将Log Buffer设置为3MB大小,就是因为当Redo Log Buffer为3MB时,以上两个条件可能同时达到,从而可以在某种程度上避免LGWR的过度激活。

3. 用户提交 当一个事务提交时,

在Redo Stream中将记录一个提交标志。在这些Redo被写到磁盘上之前,这个事务是不可恢复的。所以,在事务返回成功标志给用户前,必须等待LGWR写完成。进程通知LGWR写,并且以Log File Sync事件开始休眠,超时时间而1秒。 Oracle的隐含参数_wait_for_sync参数可以设置为False以避免Redo File Sync的等待,但是就将无法保证事务的恢复性。 sys@NEI> @GetHidPar Enter value for par: wait_for_sync old 4: AND x.ksppinm LIKE '%&par%' new 4: AND x.ksppinm LIKE '%wait_for_sync%' NAME VALUE DESCRIB ------------------------------ -------------------- ------------------------------------------------------------ _wait_for_sync TRUE wait for sync on commit MUST BE ALWAYS TRUE 注意:在递归调用(RecurSive Calls)中的提交(比如过程中的提交)不需要同步Redo直到需要返回响应给用户。因此递归调用仅需要同步返回给用户调用之前的最后一次Commit操作的RBA。 存在一个SGA变量用以记录Redo线程需要同步的Log Block Number。如果多个提交在唤醒LGWR之前发生,此变量记录最高的Log Block Number,在此之前的所有Redo都将被写入磁盘。这有时候称为组提交(Group Commit)。

4. 在DBWn写之前

如果DBWR将要写出的数据的High RBA超过LGWR的On-Disk RBA,DBWR将通知LGWR去执行写出(否则这部分数据在Recovery时将无法恢复)。在Oracle 8i之前,此时DBWR将等待log file sync事件;从Oracle 8i开始,DBWR把这些Block放入一个延迟队列,同时通知LGWR执行Redo写出,DBWR可以继续执行无需等待的数据写出。 --------------------- 本文来自 babymouse1212 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/babymouse1212/article/details/71078560?utm_source=copy

posted on 2018-09-24 11:01  知点网  阅读(189)  评论(0编辑  收藏  举报