在RAC数据库中为了一致性读,需要将Commit SCN同步/传播到所有的节点上。SCN同步/传播的主要方法有两种:Lamport SCN 和 immediate commit propagation (BOC)。
10gR1 及以下版本默认使用Lamport SCN,SCN在实例间传递是通过GCS MESSAGE来传递的,因此会存在一定的延时,在某些情况下,如果不同实例的SCN不能及时传递,多个节点之间就可能看到不同的数据,导致逻辑错误,Oracle可以通过一个参数来控制SCN的传播延时,这个参数是MAX_COMMIT_PROPAGATION_DELAY,在Oracle9i及Oracle10gR1中,其缺省值是700(7秒),确保SCN传播不得超过7秒,但是7秒已经是一个很长的时间参数。一般每3秒LCK进程就会进行一次跨实例数据交换。如果将该参数设置为0~99,就会禁用Lamport方式,使用BOC方式进行SCN同步。对于一些实时性要求高的RAC数据库Lamport SCN方式是不可取的。如果希望commit SCN 立刻同步/传播到所有节点,手动修改参数MAX_COMMIT_PROPAGATION_DELAY=1
从10gR2开始默认使用immediate commit propagation (BOC),BOC即一个节点上的commit SCN 立刻同步/传播到所有节点,参数_immediate_commit_propagation 设置为TRUE.
SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ FROM SYS.x$ksppi x, SYS.x$ksppcv y WHERE x.indx = y.indx AND x.ksppinm LIKE '%&par%'
2 /
Enter value for par: _commit
NAME VALUE DESCRIB
---------------------------------------- -------------------- ------------------------------------------------------------
_immediate_commit_propagation TRUE if TRUE, propagate commit SCN immediately
max_commit_propagation_delay 0 Max age of new snapshot in .01 seconds
下面是BOC的工作过程:
1. user session 执行提交(commit),user session会通知LGWR进程将redo buffer中的信息写入到redo log file。
2. LGWR进程收到user session通知后,将redo buffer中的信息写入redo log file,同时LGWR 将COMMIT SCN 同步/传播给远程的数据库实例的LMS 进程。
3. 远程数据库实例的LMS将commit SCN同步到本地SCN,然后通知commit实例的LMS,表示SCN 同步已经完成。
4. 当commit 实例的LMS接收到所有远程数据库实例的LMS的通知后,commit 实例的LMS再通知本地的LGWR 所有节点SCN同步已经完成。
5. LGWR 在完成了IO 操作和LMS进程通知后,LGWR通知user session commit 成功。user session在没有收到LGWR通知前,一直处于等待log file sync。
wait for scn ack是实例间进行scn同步的等待事件。但是由于等待事件 'wait for scn ack' 不能给出足够的信息量度LGWR发出BOC信息以及收到ACK信息的时间。在10.2.0.5及11gR2中,将增加了一个新的统计信息'redo write broadcast ack time'用于辅助的时间统计。
redo write broadcast ack count -Number of times a commit broadcast acknowledgment has not been received by the time when the corresponding log
write is completed.
redo write broadcast ack time- Total amount of the latency associated with broadcast on commit beyond the latency of the log write (in microseconds).