三、Redo byte address (RBA)
Oracle instance
的
redo thread
产生的最近的日志条目可以通过
RBA
(
redo byte address
)来寻址,一个
RBA
包括如下的三部分:
Ø
Log file sequence number 4 bytes
Ø
Log file block number 4 bytes;
Ø
日志开始的时候得块内
offset 2 bytes
RBA
在他们的
redo thread
内不必不同,因为用
RESETLOG
方式开打数据库的时候,所有的
redo thread
都可以设置
log file sequence number
为
1
。
RBA
在如下的应用中比较重要:
对于
Daba buffer cache
中的
dirty block
,低的
RBA
是最早改变的数据块产生日志的地址,高的
RBA
是最近变化的产生的日志的地址。
Dirty buffers are maintained on the buffer cache checkpoint queues in low RBA order. The checkpoint RBA is the point up to which DBWn has written buffers from the checkpoint queues if incremental checkpointing is enabled -- otherwise it is the RBA of last full thread checkpoint. The checkpoint RBA is copied into the checkpoint progress record of the controlfile by the checkpoint heartbeat once every 3 seconds. Instance recovery, when needed, begins from the checkpoint RBA recorded in the controlfile. The target RBA is the point up to which DBWn should seek to advance the checkpoint RBA to satisfy instance recovery objectives.
The on-disk RBA is the point up to which LGWR has flushed the redo thread to the online log files. DBWn may not write a block for which the high RBA is beyond the on-disk RBA. Otherwise transaction recovery (rollback) would not be possible, because the redo needed to undo a change is always in the same redo record as the redo for the change itself.
The term sync RBA is sometimes used to refer to the point up to which LGWR is required to sync the thread. However, this is not a full RBA -- only a redo block number is used at this point.
The low and high RBAs for dirty buffers can be seen in X$BH. (There is also a recovery RBA which is used to record the progress of partial block recovery by PMON.) The incremental checkpoint RBA, the target RBA and the on-disk RBA can all be seen in X$TARGETRBA. The incremental checkpoint RBA and the on-disk RBA can also be seen in X$KCCCP. The full thread checkpoint RBA can be seen in X$KCCRT.
(
在
buffer cache
中的
dirty buffer
中要注意,
low RBA
是指最近一次
clean(block
中已经不再有有用数据
)
后发生了第一次改变时的
block
的的
redo
的位置,
high RBA
是最近一次发生改变时该
block
的
redo
的位置
(low
和
high
是针对同一个
block
在不同时期发生了变化,变化之间没有被
clean,
可能还没有来得及被写入磁盘就又被更新了
)
。脏数据块在
检查点写队列里面,按照
low RBA
排列,
checkpoint RBA
标志
DBWn
已经从写队列里面写到磁盘了的
buffers
(表示写到了哪里)如果增量检查点是激活的(前一个检查点没有结束新的检查点又发生了),否则就是标志最近一次完整的检查点发生之后
,checkpoint RBA
每
3
秒别写入控制文件一次,实例恢复的时候如果需要的话就从控制文件中的
checkpoing RBA
开始
,target RBA
是该
checkpoint RBA
所处的没有完成的检查点的
RBA,
从这里开始就可以找到
checkpoint RBA
On-disk RBA
是指
LGWR
已经写到
log file
中的位置,
DBWn
不能写一个
block
到磁盘,假如
high RBA
高于
ON-DISK RBA
(因为这样的话恢复的时候有问题,这个时候
DBWn
就通知
LGWR
写日志文件,也就是写进磁盘的
block
的
redo
一定要先写进
log file,
这个很容易理解);否则事务恢复或者回滚将不可能,因为重做的时候需要
撤消信息,而撤消信息是和
重做信息放在一个重做记录里面的
)
什么是
checkpoint?
checkpoint
是一个数据库事件,它将已修改的数据从高速缓存刷新到磁盘,并更新控制文件和数据文件。
什么时候发生
checkpoint?
我们知道了
checkpoint
会刷新脏数据,但什么时候会发生
checkpoint
呢?以下几种情况会触发
checkpoint
。
1.
当发生日志组切换的时候
2.
当符合
LOG_CHECKPOINT_TIMEOUT
,
LOG_CHECKPOINT_INTERVAL
,
fast_start_io_target,fast_start_mttr_target
参数设置的时候
3.
当运行
ALTER SYSTEM SWITCH LOGFILE
的时候
4.
当运行
ALTER SYSTEM CHECKPOINT
的时候
5.
当运行
alter tablespace XXX begin backup
,
end backup
的时候
6.
当运行
alter tablespace ,datafile offline
的时候
;
增量检查点(
incremental checkpoint
)
oracle8
以后推出了
incremental checkpoint
的机制,在以前的版本里每次
checkpoint
时都会做一个
full thread checkpoint,
这样的话所有脏数据会被写到磁盘,巨大的
i/o
对系统性能带来很大影响。为了解决这个问题,
oracle
引入了
checkpoint queue
机制,每一个脏块会被移到检查点队列里面去,按照
low rdb
(第一次对此块修改对应的
redo block address
)来排列,靠近检查点队列尾端的数据块的
low rba
值是最小的,而且如果这些赃块被再次修改后它在检查点队列里的顺序也不会改变,这样就保证了越早修改的块越早写入磁盘。每隔
3
秒钟
ckpt
会去更新控制文件和数据文件,记录
checkpoint
执行的情况。
这里应该是只更新控制文件,每
3
秒不是更新数据文件
说
记录
checkpoint
的执行情况,这个说法,没错,但不够详细,应该说,由于增量检查点和
checkpoint queue
的原理,
ckpt
进程每次只是告诉
dbwr
,写
dirty buffer
将要一直写到最新这个位置,仅仅是告诉
dbwr
一个
checkpoint queue
中的结束点,而
ckpt
每
3
秒中,在控制文件中报告一下
dbwr
最新写入的位置。
这样使得,比如数据库要做恢复的时候(
instance recovery
)可以从这个最新位置开始做恢复,而不是从数据文件中的
checkpoint scn
开始做恢复,这样将缩短恢复时间,尤其是
instance crash
的情况下启动更快
另外要注意的是,检查点发生的时候,
ckpt
去更新数据文件头和控制文件,并不是把当前检查点发生时候的
scn
更新进去,而是把上一次
dbwr
写入已经完成的检查点发生时候的
scn
更新进去
,也就是说,更新控制文件和数据文件头
是
滞后于检查点的发生的,这个从恢复的原理也很容易理解,因为检查点发生的时候
dirty buffer
还没有写入,自然不能立即更新成当前的
scn
了。
四、Redo Write Triggers
四种情况下会引起
lgwr
执行写操作
1
、当
lgwr
空闲的时候,处于
rdbms ipc message
等待状态,三秒超时(
dbwn
也是一样)超时后,
lgwr
发现需要写日志,然后就写。
2
、当
process
在
log buffer
中分配
block
,如果
log buffer
占用的大于或者等于
_log_io_size
参数设定值,并且
lgwr
没有
active
,那么
lgwr
被激活进行写操作。默认值为
log buffer
的
1/3
。
8i
之后为
1M
,除非显示设定
,_log_io_size
这样的参数在
v$ksppsv
中设定为
0
。
3
、当一个事务
commit
的时候,产生一个
commit marker
。但这种情况下,事务不能被回滚,直到
log block
被写进
disk
当中。所以在
process
结束事务的时候返回给用户的时候必须等待
lgwr
写完所有对应的
log block
,这时候
process
处于
log file sync
状态,超时为
1
秒。这时可以设定
_wait_for_sync
为
false
,这样可以避免
redo sync
的等待,但当
instance failure
的时候,不能保证事务的可恢复性。
recursive call
知道返回给用户的时候才需要等待
sync
。
sga
变量
b
用来连接
log block number
和需要同步的
redo thread
。如果在
lgwr
超时之前好几个事务
commit
的话,
b
将记录需要同步的最高的
log block number
,
commit marker
将一次性写入
disk
。这就是所谓的
group commit
4
、当
dbwn
需要写一个或者更多的
block
,他们的
redo rba
超过了
lgwr
的
on_disk rba
的时候,会引发
lgwr
写操作。
8i
以后,
dbwn
会将
blocks
放入延迟写的队列当中,然后要求
lgwr
同步最高的
rba
,
dbwn
立即执行其他的操作。
8i
以前,
dbwn
需要进入
log file sync
状态等待。