首页 >数据库 >mysql教程 >Oracle事务表实验详解

Oracle事务表实验详解

WBOY
WBOY原创
2016-06-07 15:45:311120浏览

回滚段头中,有一项非常重要的信息,就是事务表。对事务表频繁的访问,可能会造成回滚段头的争用。了解什么样的操作会访问事务表,对于了解回滚段头争用的原因非常重要。下面我们来做一些实验来验证一下,什么样的操作才会访问事务表。 首 先简单介绍一个视

回滚段头中,有一项非常重要的信息,就是事务表。对事务表频繁的访问,可能会造成回滚段头的争用。了解什么样的操作会访问事务表,对于了解回滚段头争用的原因非常重要。下面我们来做一些实验来验证一下,什么样的操作才会访问事务表。
    
    首 先简单介绍一个视图,备份x$bh.对这个视图我想大家都有一定的了解,bh即buffer header 的简写。在buffer  header中有 一个TCH 列,表示块被访问的次数。我们通过他来验证事务表什么时候被访问。需要注意的是。TCH列每3秒,才会重新计算一次,3秒之内无论访问某一个 块多少次。TCH列只会增加1.
    
    在会话A开启一个事务后:
    
    步骤一:通过v$transaction视图找到XID
    
    SQL> select xidusn,ubablk,ubafil from v$transaction;
    
    XIDUSN     UBABLK     UBAFIL
    
    ---------- ---------- ----------
    
    13         97          5
    
    步骤二:通过回滚段编号,可得知事务所占回滚段名,并用此查找事务头块号,文件号
    
    SQL> select header_block,header_file from dba_segments where segment_name='_SYSSMU13$';
    
    HEADER_BLOCK HEADER_FILE
    
    ------------ -----------
    
    41           5
    
    步骤三:查看x$bh视图中,TCH值的增加。
    
    SQL> select addr,tch from x$bh where dbarfil=5 and dbablk=41;
    
    ADDR            TCH
    
    -------- ----------
    
    080B5208         41
    
    步骤四:查找完TCH后,马上执行要测试的命令(会话B),
    
    SQL> select * from jj_3;
    
    ID NA
    
    ---------- --
    
    1 aa
    
    2 aa
    
    3 aa
    
    4 aa
    
    5 CN
    
    步骤五:再次查看x$bh视图
    
    SQL> select addr,tch from x$bh where dbarfil=5 and dbablk=41;
    
    ADDR            TCH
    
    -------- ----------
    
    080B5208         42
    
    注意:步骤三四五应尽快完成。避免oracle的其他内部操作影响测试结果。(因为oracle内部的操作也会造成回滚段头的tch值增加,特别在10G中,这种情况更为明显,不过我没有跟踪是什么oracle的内部操作造成的)
    
    小结:从结果集来看,在另一会话中访问未提交数据的select语句会访问事务表,那么其他的DML操作呢?(希望大家也都试试,我的结果是都会增加TCH值)。上面我的步骤四是全表扫描。

 

如果我的表有两个块,分别是块一块二,在块一中修改行A,按照rowid访问块一中的行B,这样会访问事务表吗?如果
    
    按照rowid访问块二中的行,会访问事务表吗?下面我来实验下看结果是什么:
    
    步一:利用函数查看该表的块号。
    
    SQL> select rowid,dbms_rowid.rowid_block_number(rowid) from jj_3;
    
    ROWID              DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
    
    ------------------ ------------------------------------
    
    AAAMvjAAKAAAAEdAAA                                  285
    
    AAAMvjAAKAAAAEdAAB                                  285
    
    AAAMvjAAKAAAAEdAAC                                  285
    
    AAAMvjAAKAAAAEeAAA                                  286
    
    步二: 在B会话中通过AAAMvjAAKAAAAEdAAC(在块285上)修改表。
    
    SQL> update jj_3 set id=10 where rowid='AAAMvjAAKAAAAEdAAC'(在块285上);
    
    已更新 1 行。
    
    步三: 在A会话中通过AAAMvjAAKAAAAEdAAA(在块285上)查看行
    
    SQL> select * from jj_3 where rowid='AAAMvjAAKAAAAEdAAA'(在块285上);
    
    ID NA
    
    ---------- --
    
    4 aa
    
    在做步一和二之前,先查看一下X$BH,因为他会因为oracle的内部操作而增加,
    
    实验前查看结果:
    
    SQL> select addr,tch from x$bh where dbarfil=5 and dbablk=41;
    
    ADDR            TCH
    
    -------- ----------
    
    080B51BC         63
    
    实验后查看结果:
    
    SQL> select addr,tch from x$bh where dbarfil=5 and dbablk=41;
    
    ADDR            TCH
    
    -------- ----------
    
    080B51BC         64
    
    结论一:在块一中修改行A,按照rowid访问块一中的行B,这样会访问事务表;

    再试试不同的块
    
    操作前先查看下X$BH:
    
    SQL> select addr,tch from x$bh where dbarfil=5 and dbablk=41;
    
    ADDR            TCH
    
    -------- ----------
    
    080B51BC         67
    
    接着刚才的实验,我又访问了不同的块:
    
    SQL> select * from jj_3 where rowid='AAAMvjAAKAAAAEeAAA'(在块286上);
    
    ID NA
    
    ---------- --
    
    4 aa
    
    再次查看X$BH的结果是:
    
    SQL> select addr,tch from x$bh where dbarfil=5 and dbablk=41;
    
    ADDR            TCH
    
    -------- ----------
    
    080B51BC         67
    
    结果很明显了,用rowid访问不同的块,是不会增加TCH值的。也就是说不会有CR块产生。
    
    在晶晶实验六中,已经证明了在生成CR块时,oracle可以根据数据块头部的ITL槽中的UBA,找到存放数据块回滚信息的回 滚块和回滚记录,通过这个UBA就可以构造CR块咯,oracle为什么还要再去访问事务表呢?这是因为,oracle的提交有时会 是延迟提交。oracle并不清除延迟提交所涉及的块中的事务信息,如:事务所占ITL槽和行锁。而把清除事务信息这个操作 放到了以后的块清除中(块清除在以后的实验会详细讲述),oracle这样做的目的是为加快提交速度。如果一个事务涉及到了过多的块,单单是提交时清除每个块中的事务信息就需要耗费很长时间。这降低了提交速度。有可能使提交成为最易 引起争用的操作。当事务提交时,对事务所涉及的块,不做任何操作,块将保持事务仍在持续时的信息。当一个select操作 查询到这个块时,ITL槽中的提交标志为未提交,但实际上这个事务是已经提交的。就是因为有了延迟提交oracle无法根 据ITL槽中的提交标志来判断一个块中的事务是否真的提交。他必须根据ITL中的XID 去访问事务表。才能确定此块中的事务是否真的提交。在生成CR块前,oracle先要判断是否真的有必要为此块生成CR块。这就要去访问事务表。

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn