晶晶实验六自己动手构造CR块.docx

上传人:b****5 文档编号:7499265 上传时间:2023-01-24 格式:DOCX 页数:8 大小:20.81KB
下载 相关 举报
晶晶实验六自己动手构造CR块.docx_第1页
第1页 / 共8页
晶晶实验六自己动手构造CR块.docx_第2页
第2页 / 共8页
晶晶实验六自己动手构造CR块.docx_第3页
第3页 / 共8页
晶晶实验六自己动手构造CR块.docx_第4页
第4页 / 共8页
晶晶实验六自己动手构造CR块.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

晶晶实验六自己动手构造CR块.docx

《晶晶实验六自己动手构造CR块.docx》由会员分享,可在线阅读,更多相关《晶晶实验六自己动手构造CR块.docx(8页珍藏版)》请在冰豆网上搜索。

晶晶实验六自己动手构造CR块.docx

晶晶实验六自己动手构造CR块

晶晶实验六自己动手构造CR块

上一篇/下一篇2008-02-2016:

01:

23/个人分类:

晶晶oracle实验系列

查看(2764)/评论(36)

一、查询魔术

步1:

在会话17中发布如下声明:

17>varxrefcursor

17>execopen:

xforselectsubstr(c,1,5),idfromt8;

PL/SQL过程已成功完成。

步2:

在会话13删除T8的所有记录且提交:

13>deletet8;

已删除10行。

13>commit;

提交完成。

步3:

在会话17中输出游标X的所有行:

17>printx

SUBSTR(C,1ID

--------------------

g7

h8

i9

J10

AA1

B2

C3

D4

E5

f6

已选择10行。

我们在会话13中已删除且已提交,但在会话17中还是显示出了T8中的所有行,这是为什么呢?

1)在步1打开游标,但此时并没有执行、执取,在会话17的PGA中,将会开辟一块内存存贮此游标。

在游标的相关信息中,有一条就是游标打开是的SCN,假若此

时的SCN是1000。

2)在步2中对表T8进行了操作,并提交。

Oracle每个数据块的头部,都记有此块当前的SCN值,此SCN值随着对块的更新而变化。

假如,我们在步2更新T8表时,

SCN是1200,这个值将被记入块头部的SCN值。

3)在步3我们发布Printx声明,此声明将完成执行、抓取等步骤。

在从T8表的相关块中抓取行时,Oracle会将打开游标时的SCN和块本身的SCN相比较,如果发现

后者大于前者,证明打开游标是在更新表之前进行的,Oracle将会在回滚段中寻找小于游标SCN的信息,构造一个在打开游标之前的块,这就是CR块了。

如果回滚

段中的T8表的信息已经被覆盖,将会报告一个ORA-01555快照太老错误。

执行时间过长的查询,有时也会报出这个错误。

二、SCN

SCN就是Oracle内部的一个记时机值,也就是Oracle的内部时钟。

在9i之后,我们可以通过如下的方式获得当前的SCN号:

scott@MYTWO>

selectscn,to_char(scn,’xxxxxxx’)from(selectdbms_flashback.get_system_change_numberSCNfromdual);

SCN

----------

8727805

在几乎所有的地方,你都能见到SCN。

在事务表、回滚块中的回滚记录、数据块、日志文件等等,我们上面曾提到过,在游标中,记录的也有游标打开时的SCN。

(在eygle的深入浅出oracle中有关SCN号更详细的介绍,18页)

三、构造CR块

Oracle会在三种情况下去读回滚段构造CR块:

1.只要数据块上有锁,Oracle将会构造CR块。

2.游标的SCN小于块的SCN,证明块在游标打开之后又被修改过了,这就要去构造CR块。

3.闪回查询中,要求的SCN小于块的SCN,也要去构造CR块。

构造CR块

步1:

先观察表T8的行分布情况:

ROWIDBLOCK#CID

------------------------------------------------

AAAB3LAAFAAAf/mAAA131046a1

AAAB3LAAFAAAf/mAAB131046b2

AAAB3LAAFAAAf/mAAC131046c3

AAAB3LAAFAAAf/nAAA131047d4

AAAB3LAAFAAAf/nAAB131047e5

AAAB3LAAFAAAf/nAAC131047f6

AAAB3LAAFAAAf/oAAA131048g7

AAAB3LAAFAAAf/oAAB131048h8

AAAB3LAAFAAAf/oAAC131048i9

AAAB3LAAFAAAf/pAAA131049j10

步2:

发布更新命令

13>updatet8setc=upper(c)whereid<=2;

已更新2行。

13>commit;

提交完成。

13>updatet8setc='A1'whereid<=1;

已更新1行。

13>updatet8setc='A2'whereid<=2;

已更新2行。

13>updatet8setc='B2'whereid<=2;

已更新2行。

13>commit;

提交完成。

换到其他会话,

17>updatet8setc='aa1'whereid<=1;

已更新1行。

17>updatet8setc='bb2'whereid=2;

已更新1行。

17>commit;

提交完成。

17>updatet8setc='aaa1'whereid<=1;

已更新1行。

17>updatet8setc='bbb2'whereid=2;

已更新1行。

17>updatet8setc='aaaa1'whereid<=1;

已更新1行。

17>updatet8setc='bbbb2'whereid=2;

已更新1行。

17>commit;

提交完成。

再换个会话:

10>updatet8setc='aaaaa10'whereid=1;

已更新1行。

10>updatet8setc='bbbbb10'whereid=2;

已更新1行。

10>commit;

提交完成。

10>updatet8setc='az'whereid=1;

已更新1行。

10>updatet8setc='by'whereid=2;

已更新1行。

此时的SCN是

18>selectdbms_flashback.get_system_change_numberSCNfromdual;

SCN

----------

8729612

总结一下

行1的变化a->A->A1A2B2->aa1->aaa1aaaa1->aaaaa10->az

行2的变化b->B->B2 ->bb2->bbb2bbbb2->bbbbb10->by

下面开始构造CR块,首先说一下末提交时CR块的构造:

步3:

末提交时CR块的构造:

接着上面的修改,如果我们在会话16发布查询T8表的声明:

16>select*fromt8whereid<=3;

由于最后一次修改没有提交,假如此时有其他会话访问行1或行2,就回发生回滚操作,从而构造一个CR块。

让我们自己来回滚一下,感受一下Oracle的回滚操作

到底做了什么:

首先DUMP块131046:

altersystemdumpdatafile5block131046;

在事务的头部,有一块这样的结构:

ItlXidUbaFlagLckScn/Fsc

0x010x0018.008.0000001a0x03800073.000e.02----2fsc0x0000.00000000

0x020x0019.007.000000200x03800053.0037.01C---0scn0x0000.008533f6

它被叫做ITL,InterestedTransactionList,相关事务列表。

此表中每一行,按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,我们可以了解到,此块中有一个末提交的事务,那么此事务影响了几行呢,或者说此事务修改了几行呢?

在下面行信息中,有:

tab0,row0,@0xba7

tl:

1009fb:

--H-FL--lb:

0x1cc:

2

col0:

[1000]

617a2020202020202020202020202020202020202020202020

这其中的lb:

0x1,就是指此行对应事务0x01,或说此行是事务0x01修改的行,或说事务0x01锁住了此行。

它现在的值是617a,正是“az”。

如果在其他会话上发布查询,Oracle首先检查ITL,一但发现某块上尚有末提交的事务,根据其UBA,马上开始构造其CR块,而不管会话所检索的行,是

否是事务相关的。

块131046上有末提交事务:

0x010x0018.008.0000001a0x03800073.000e.02----2fsc0x0000.00000000

其UBA是0x03800073.000e.02,即14号文件,115块,序列号14,第2条回滚记录。

下面DUMP115块:

altersystemdumpdatafile14block115;

在DUMP文件中找到根据irb:

0x2,找到115块中第2条回滚记录,它对应131046第1行,前映像值为62626262623130,即“bbbbb10”。

再根据其rci:

0x01

,向上找到第一条回滚记录,它对应131046第0行,前映像值为61616161613130,即“aaaaa10”。

131046块中当前值是:

Slot0(行1):

617a(“az”)相关末提交事务0x1

Slot1(行2):

6279(“by”)相关末提交事务0x1

Slot2(行3):

63(“c”)无相关事务

通过读事务0x1的回滚块,将前映像信息写进131046,替换事务0x1对应的行,在内存中生成一个新的块:

Slot0(行1):

61616161613130(“aaaaa10”)相关末提交事务0x1

Slot1(行2):

62626262623130(“bbbbb10”)相关末提交事务0x1

Slot2(行3):

63(“c”)无相关事务

这个新生成的块,块的编号仍是131046,在内存中,它的HASH位置会和原来的131046处于同一HASHCacheBufferChain。

它就是131046的CR块。

CR块的构造到现

在还没有完成,我们用前像映像行值替换了当前的行值,我们最后一步所做的更新并仅仅修改了行的值,上面我们讲到,每个块头有一个ITL,它初始有两个槽,

每个末提交的事务,将占用一个槽,可以随事务增多而扩充。

如果事务已提交,它占用的槽会被下一个事务覆盖。

因此,我们最后在会话10中做的更新,将覆盖

131046的一个已提事务的ITL槽,这个被覆盖的ITL槽被记进事务回滚链头部块中,如下所示:

op:

Litl:

xid:

0x001a.010.00000011uba:

0x03800085.000e.01

flg:

C---lkc:

0scn:

0x0000.00853185

我们应该用它替换131046中当前的0x01槽:

ItlXidUbaFlagLckScn/Fsc

0x010x0018.008.0000001a0x03800073.000e.02----2fsc0x0000.00000000

0x020x0019.007.000000200x03800053.0037.01C---0scn0x0000.008533f6

替换为:

ItlXidUbaFlagLckScn/Fsc

0x010x001a.010.000000110x03800085.000e.01C---0fsc0x0000.00853185

0x020x0019.007.000000200x03800053.0037.01C---0scn0x0000.008533f6

好了,到现在,我们终于构造了一个131046的CR块:

ItlXidUbaFlagLckScn/Fsc

0x010x001a.010.000000110x03800085.000e.01C---0fsc0x0000.00853185

0x020x0019.007.000000200x03800053.0037.01C---0scn0x0000.008533f6

Slot0(行1):

61616161613130(“aaaaa10”)相关末提交事务0x1

Slot1(行2):

62626262623130(“bbbbb10”)相关末提交事务0x1

Slot2(行3):

63(“c”)无相关事务

现在,131046的CR块中的ITL中,所有事务都已提交,我们的回滚是否可以到此为止呢?

还不行,Oracle还要对比一下查询游标打开时的SCN,如果大于上面CR块中ITL的最大提交SCN:

8533f6,证明查询发生在事务结束之后,查询时的SCN大致是:

18>selectscn,to_char(scn,'xxxxxxxxxx')from(selectdbms_flashback.get_system_change_numberSCNfromdual);

SCNTO_CHAR(SCN

---------------------

87346498547b9

后于CR块ITL中最大提交SCN,好,到此为止,回滚结束。

如果游标的SCN前于ITL中最大提交SCN,Oracle仍要继续回滚。

步4:

闪回查询时CR块的构造:

假如用户发布如下声明:

selectsubstr(c,1,5),idfromt8asofscn8728960whereid<=3;

此声明指定读取SCN为8728960时块中的行。

这就是闪回查询。

查询要求SCN:

853180,前于步3时构造的CR块,因此,需要继续向前回滚。

仍然根据ITL中的UBA信息,取出前映像,来构造另一个CR块。

问题时,ITL有两个槽,

我们该从哪个机槽的UBA回滚呢。

最好的方法是从SCN最大的哪个。

此处是槽0x02:

ItlXidUbaFlagLckScn/Fsc

0x020x0019.007.000000200x03800053.0037.01C---0scn0x0000.008533f6

UBA中显示,此事务的回滚链尾块在14号文件,83号块,中第1条记录,回滚块序列号是55。

altersystemdumpdatafile14block83;

打开DUMP文件,首先要检查一下,此回滚块是否已被别的事务覆盖,检查方法,非常简单,看此UnDo块的Seq值:

UNDOBLK:

xid:

0x0019.008.00000021seq:

0x37cnt:

0x11irb:

0x11icl:

0x0flg:

0x0000

仍是0x37,和UBA中所记的一样,证明此回滚块还末被覆盖。

取出前映像,对应5号文件131046块的Slot1(行2)的第0列:

6262626232,即“bbbb2”。

续沿回滚链向上,根据rdba:

0x03800052,回滚链上一块在82块中,继续DUMP:

altersystemdumpdatafile14block82;

打开DUMP文件,检查块的Seq值,仍是37。

取出前映像,对应5号文件131046块的Slot0(行1)0列,值为:

6161616131,即“aaaa1”。

此回滚记录已是回滚链头,被覆盖的ITL槽是:

op:

Litl:

xid:

0x0018.005.0000001auba:

0x03800072.000e.08

flg:

C---lkc:

0scn:

0x0000.00853171

构造一个新的CR块:

ItlXidUbaFlagLckScn/Fsc

0x010x001a.010.000000110x03800085.000e.01C---0fsc0x0000.00853185

0x020x0018.005.0000001a0x03800072.000e.08C---0scn0x0000.00853171

0x020x0019.007.000000200x03800053.0037.01C---0scn0x0000.008533f6

Slot0(行1):

61616161613130(“aaaaa10”)相关末提交事务0x1

Slot1(行2):

62626262623130(“bbbbb10”)相关末提交事务0x1    --红色字体为应该覆盖的信息

Slot0(行1):

6161616131(“aaaa1”)

Slot1(行2):

6262626232(“bbbb2”)

Slot2(行3):

63(“c”)

如果你发布如下声明:

selectsubstr(c,1,5),idfromt8asofscn8728960whereid<=3;

这将会先构造步3时的CR块,再构造此步中的CR块,这两个CR块都是131046的CR块,因此,步4时的CR块会覆盖步3时的CR块。

也就是说,在一次查询中,Oracle对

应一个数据块,只会在内存创建一个CR块。

好了,我们的查询到此可以为止了吗,对比SCN,查询SCN:

853180,ITL中最大SCN:

853185。

ITL中最大SCN仍后于查询SCN。

继续回滚:

步5:

继续回滚:

根据ITL中最大SCN槽的Uba,

ItlXidUbaFlagLckScn/Fsc

0x010x001a.010.000000110x03800085.000e.01C---0fsc0x0000.00853185

回滚链尾块在14号文件,133回滚块,第1条回滚记录,序列号是14。

DUMP133块:

altersystemdumpdatafile14block133;

打开DUMP文件,检查块的Seq值,仍是0xe。

取出前映像,对应5号文件131046块的Slot1(行2)0列,值为:

62626232,即“bbb2”。

回滚链上一块在rdba:

0x03800084,132块中:

altersystemdumpdatafile14block132;

找到最后一条回滚记录,它的前映像对应5号文件131046块的Slot0(行1)0列,值为61616131,即“aaa1”,但它并是回滚链头,根据它的Rci0x02,继

续向上,找到0x02条回滚记录,它对应对应5号文件131046块的Slot1(行2)0列,626232,即“bb2”,还没完,再向上,是131046块中Slot0(行1)0列,

616131,即“aa1”,此条回滚记录的Rci已经是0了,已经到了回滚链头,被覆盖的ITL槽是:

op:

Litl:

xid:

0x0017.003.00000045uba:

0x03800021.0021.03

flg:

C---lkc:

0scn:

0x0000.008530fd

ItlXidUbaFlagLckScn/Fsc

0x010x001a.010.000000110x03800085.000e.01C---0fsc0x0000.00853185

0x010x0017.003.000000450x03800021.0021.03C---0fsc0x0000.008530fd

0x020x0018.005.0000001a0x03800072.000e.08C---0scn0x0000.00853171

Slot0(行1):

6161616131(“aaaa1”)

Slot1(行2):

6262626232(“bbbb2”)

Slot0(行1):

616131(“aa1”)

Slot1(行2):

626232(“bb2”)

Slot2(行3):

63(“c”)

查询的SCN是853180,ITL中最大SCN是853171,查询SCN大于ITL中的SCN,说明查询发生在事务后,好了,到此,我们这一次CR块构造完毕。

此次生成的131046的

CR块会覆盖步4时生成的,一个块,在一次查询中,只会产生一个CR块。

根据我们的操作顺序:

a->A->A1A2B2->aa1->aaa1aaaa1->aaaaa10->az

b->B->B2 ->bb2->bbb2bbbb2->bbbbb10->by

    ↑

我们已经回到了箭头所指处。

我们可以一直向前回塑,直到T8的行被插入131046时,或者,回滚段被覆盖时。

假若我们又向前回塑,但回滚块的Seq和我们要求的

不一样,证明此块被覆盖了,此时Oracle会报告Ora-01555错误。

我们只需让回滚段的区足够多,这样它每次绕回的时间必然加长。

这样,回滚段必然可更长时间

的保持已提交事务的回滚信息。

在X$BH视图中上,有一个CR_SCN_BAS列,显示CR块的最大SCN:

18>selectfile#,DBABLK,state,tch,cr_scn_bas,to_char(cr_scn_bas,'xxxxxxxx')SCNfromx$bh

wherefile#=5anddbablk=131046;

FILE#DBABLKSTATETCHCR_SCN_BASSCN

-----------------------------------------------------------------------------------------

5131046308728964853184

上面的0x853184就是咯。

旁边的8728964是他的10进制值.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1