下面开始构造CR块,首先说一下末提交时CR块的构造: 步3:末提交时CR块的构造: 接着上面的修改,如果我们在会话16发布查询T8表的声明: 16> select * from t8 where id<=3; 由于最后一次修改没有提交,假如此时有其他会话访问行1或行2,就回发生回滚操作,从而构造一个CR块。让我们自己来回滚一下,感受一下Oracle的回滚操作
到底做了什么: 首先DUMP块131046: alter system dump datafile 5 block 131046; 在事务的头部,有一块这样的结构: Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0018.008.0000001a 0x03800073.000e.02 ---- 2 fsc 0x0000.00000000 0x02 0x0019.007.00000020 0x03800053.0037.01 C--- 0 scn 0x0000.008533f6 它被叫做ITL,Interested Transaction List,相关事务列表。此表中每一行,按Oracle惯用的说法,又叫一个槽,SLOT。当有事务修改此块中的数据时,或者说此块中有事务发生时,就在ITL中占用一个槽。下面我们了解一下ITL中的信息。 第一列,ITL编号,共有两个,分别是0x01,0x02,随着此块中事务的增多,槽数量也会增多。 第二列,Xid,事务Xid编号,Xid共分三段,我们在上文中已经讲过,回滚段编号.槽号.序列号。我们来看0x01事务,它占用24号回滚段的第8个槽,此槽的序列号是26,即24.8.26。 第三列,UBA,回滚块地址。也分三段,分别是回滚块地址,回滚块序列号,回滚链末记录号(即irb信息)。此处0x01事务占用14号文件,115号回滚块,块序列号是14,回滚链的末记录在115的第2条记录处。 第四列,Flag,标志,共有四位,四位都是“----”,事务末提交,第一位是C,“C---”,事务已提交。 第五列,Lck,事务所修改的行的数量。这些行,都算是被事务锁住的行。 第六列,SCN/Fsc,是事务的SCN信息。0x01事务尚末提交,故此列为0。 通过上面ITL,我们可以了解到,此块中有一个末提交的事务,那么此事务影响了几行呢,或者说此事务修改了几行呢?在下面行信息中,有: tab 0, row 0, @0xba7 tl: 1009 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [1000] 61 7a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 这其中的lb: 0x1,就是指此行对应事务0x01,或说此行是事务0x01修改的行,或说事务0x01锁住了此行。它现在的值是61 7a,正是“az”。 如果在其他会话上发布查询,Oracle首先检查ITL,一但发现某块上尚有末提交的事务,根据其UBA,马上开始构造其CR块,而不管会话所检索的行,是否是事务相关的。 块131046上有末提交事务: 0x01 0x0018.008.0000001a 0x03800073.000e.02 ---- 2 fsc 0x0000.00000000 其UBA是0x03800073.000e.02,即14号文件,115块,序列号14,第2条回滚记录。下面DUMP115块: alter system dump datafile 14 block 115; 在DUMP文件中找到根据irb: 0x2,找到115块中第2条回滚记录,它对应131046第1行,前映像值为 62 62 62 62 62 31 30 ,即“bbbbb10”。再根据其rci:0x01,向上找到第一条回滚记录,它对应131046第0行,前映像值为 61 61 61 61 61 31 30,即“aaaaa10”。 131046块中当前值是: Slot 0(行1):61 7a (“az”) 相关末提交事务0x1 Slot 1(行2):62 79 (“by”) 相关末提交事务0x1 Slot 2(行3):63 (“c”) 无相关事务 通过读事务0x1的回滚块,将前映像信息写进131046,替换事务0x1对应的行,在内存中生成一个新的块: Slot 0(行1):61 61 61 61 61 31 30 (“aaaaa10”) 相关末提交事务0x1 Slot 1(行2):62 62 62 62 62 31 30 (“bbbbb10”) 相关末提交事务0x1 Slot 2(行3):63 (“c”) 无相关事务 这个新生成的块,块的编号仍是131046,在内存中,它的HASH位置会和原来的131046处于同一HASH Cache Buffer Chain。它就是131046的CR块。CR块的构造到现
在还没有完成,我们用前像映像行值替换了当前的行值,我们最后一步所做的更新并仅仅修改了行的值,上面我们讲到,每个块头有一个ITL,它初始有两个槽,每个末提交的事务,将占用一个槽,可以随事务增多而扩充。如果事务已提交,它占用的槽会被下一个事务覆盖。因此,我们最后在会话10中做的更新,将覆盖131046的一个已提事务的ITL槽,这个被覆盖的ITL槽被记进事务回滚链头部块中,如下所示: op: L itl: xid: 0x001a.010.00000011 uba: 0x03800085.000e.01 flg: C--- lkc: 0 scn: 0x0000.00853185 我们应该用它替换131046中当前的0x01槽: Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0018.008.0000001a 0x03800073.000e.02 ---- 2 fsc 0x0000.00000000 0x02 0x0019.007.00000020 0x03800053.0037.01 C--- 0 scn 0x0000.008533f6 替换为: Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x001a.010.00000011 0x03800085.000e.01 C--- 0 fsc 0x0000.00853185 0x02 0x0019.007.00000020 0x03800053.0037.01 C--- 0 scn 0x0000.008533f6 好了,到现在,我们终于构造了一个131046的CR块: Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x001a.010.00000011 0x03800085.000e.01 C--- 0 fsc 0x0000.00853185 0x02 0x0019.007.00000020 0x03800053.0037.01 C--- 0 scn 0x0000.008533f6
Slot 0(行1):61 61 61 61 61 31 30 (“aaaaa10”) 相关末提交事务0x1 Slot 1(行2):62 62 62 62 62 31 30 (“bbbbb10”) 相关末提交事务0x1 Slot 2(行3):63 (“c”) 无相关事务 现在,131046的CR块中的ITL中,所有事务都已提交,我们的回滚是否可以到此为止呢? 还不行,Oracle还要对比一下查询游标打开时的SCN,如果大于上面CR块中ITL的最大提交SCN:8533f6,证明查询发生在事务结束之后,查询时的SCN大致是: 18> select scn,to_char(scn,'xxxxxxxxxx') from (select dbms_flashback.get_system_change_number SCN from dual); SCN TO_CHAR(SCN ---------- ----------- 8734649 8547b9 后于CR块ITL中最大提交SCN,好,到此为止,回滚结束。 如果游标的SCN前于ITL中最大提交SCN,Oracle仍要继续回滚。
|