【本文根据itpub的帖子整理】
数据库中同时存在许多事务,LGWR进程在写入重做日志文件时可以采取“组提交”的方式。
一个用户提交事务时,LGWR进程开始将该进程的重做记录写入硬盘。如果在写入的过程中有其他多个用户也执行COMMIT语句提交事务,这时LGWR进程不能立即将这些事务的重做记录写入硬盘,而必须等待当前的写操作完成。当第一个事务的重做记录都被写入到硬盘中后,LGWR进程将被重做日志缓存中的数据一次性全部写入重做日志文件。
这两个commit 前面应该还有一个commit (原书中《Oracle技术实用详解: 教你如何称为10g OCP 》) , 前面那一个commit 提交,并正在通过LGWR 将重做记录写入联机日志文件的时候(还没有完成), 这时候其他server processes 也在发出更新语句后也先后发出commit 的命令(也就是下面表中这两个commit, 注意这时候这两个commit之前的commit 对应的事务还在写联机日志 ), 这时候LGWR进程不能立即将这些事务(后面两个事务及commit)的重做记录写入硬盘,而必须等待当前的写操作(这里“当前的写操作”即是指这两个commit之前的那个操作及对应的commit 的所有重做记录写入online redo 的操作)完成。当第一个事务(包含commit)的重做记录都被写入到硬盘中后,LGWR进程将被重做日志缓存中的数据一次性全部写入重做日志文件。
----------------------------------------------------------------------------------
前面还有current 的操作及commit 没有在这个表中
行号 事务id file# blk# row column value
1 T20 2 39 - - 289
2 T20 5 498 220 3 190
3 T9 2 90 - - hhh
4 T9 9 100 20 9 xxx
5 T9 commit SCN timestamp
6 T18 2 189 - - 18
7 T18 10 29 300 10 20
8 T18 commit SCN timestamp
------------------------------------------------------------------------------------
行号 事务id file# blk# row column value
1 T1 2 19 - - abc -- session1 回滚段中保存旧值
2 T1 4 120 1 2 cdf -- session1 更新新值到表的数据块
3 T20 2 30 - - 9 -- session2 回滚段中保存旧值
4 T20 5 200 20 1 10 -- session2 更新新值到表的数据块
5 T1 2 19 - - abc -- session1 回滚段中保存旧值
6 T1 4 120 2 2 xyz -- session1 更新新值到表的数据块
7 T1 commit SCN timestamp -- session1 提交
log buffer 组提交 :
下面有多个session发出的更新语句,在第一个commit发出时,会触发LGWR写联机日志文件,但是如果正在写联机日志文件的过程中(还没有完成),有其他事务也发出提交语句(比如下面的T9/T18事务发出的commit), 那么这时LGWR进程不能立即将这些事务(8~15行)的重做记录写入硬盘,而必须等待当前的写操作(1~7的重做记录写入联机日志文件)完成。当第一个事务的重做记录(1~7)都被写入到硬盘中后,LGWR进程将重做日志缓存中的数据(8~15行)一次性全部写入重做日志文件。
行号 事务id file# blk# row column value
8 T20 2 39 - - 289
9 T20 5 498 220 3 190
10 T9 2 90 - - hhh
11 T9 9 100 20 9 xxx
12 T9 commit SCN timestamp
13 T18 2 189 - - 18
14 T18 10 29 300 10 20
15 T18 commit SCN timestamp
参考: