由于表3中的实验后半段在两个实例上都对表t04209_name做了更改。对于两个实例各自回滚段上的BI而言,激活了一个回滚段的实例立刻成为该段的master实例。如上一节所述回滚段没有真正的object_id,所以使用4294950912+回滚段号作为该回滚段的object_id。到此我们自然就会得出一个有意思的推论:一个事务产生的newvalue和old value(BI)可以被两个不同的实例master:因为实例1可以update一个实例2master的数据块,new value的master自然是实例2;oldvalue由于在实例1的回滚段上所以归实例1master。这样推导下去诸如“gc [current/cr] [multiblock] request”、“gc[current/cr] [2/3]-way“、”gc [current/cr] block busy“、”gc [current/cr] grant2-way“、”gc [current/cr] [block/grant] congested“和“gc [current/cr][failure/retry]“等待事件中的current(new value)和cr(old value)分别对应的master实例有可能不是同一个。可以顺便验证一下(见表4):
实验第16步: 查看回滚段信息 在任一个实例上执行: selectrs.instance_num,rs.segment_name,rs.segment_id,rs.segment_id+4294950912from dba_rollback_segs rs;
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第17步: 查看回滚段正被哪个实例Remaster: 在任一个实例上执行: select* from v$gcspfmaster_info;
|
表4:表3实验过程中伴随的undo段GRD信息
4.能够查出某个块Master实例和Owner实例的X$表
X$KJBL描述哪一个实例是某个表的带BL锁的块的master实例(见表5)。
让表3中所描述的两个实例继续update,不要停接着做以下的实验(如果两个实例,或其中一个结束了update重新update ) 实验第18步: 在任一个实例上执行: 创建一个基于X$KJBL的视图,后续实验需要它 create or replace view myview as selectkj.file#, kj.block#, kjblname, kjblname2, kjblowner+1 "OWNER_Instance", kjblmaster+1 "MASTER_Instance", kjbllockpfrom ( selectkjblname, kjblname2, kjblowner, kjblmaster, kjbllockp, (substr ( kjblname2,instr(kjblname2,',')+1,instr(kjblname2,',',1,2)-instr(kjblname2,',',1,1)-1))/65536 file#, substr ( kjblname2, 1, instr(kjblname2,',')-1) block# from x$kjbl ) kj, ( selectblock_idblock#_begin,block_id+blocks-1block#_end, e.file_id file# from dba_extents e where e.owner='HR' and e.segment_name='T04209_UNAME' ) e where kj.block# between e.block#_begin and e.block#_endand kj.file#=e.file# order by block#; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第19步: 在任一个实例上执行: select * from myview;
从以上的查询结果可以看出:每个数据块内存拷贝在两个实例的数据库缓冲区缓存中都可以被找到,也就是说每个数据块都有两个个Owner实例,那么证明在近期有两个实例先后修改或访问过它。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第20 步: 在任一个实例上执行: selectdistinctblock#,"MASTER_Instance"from myvieworder by 1 ;
这说明:从10g以后版本开始,数据块的状态和属主等信息被存储成每128个块的信息一个master单元,即128个数据块的状态和属主等信息构成一个“gcs mastership bucket”。但是要说明以下:一个“gcs mastership bucket”不一定要存满128个块的状态和属主等信息。这样就能理解:超过128个块的表的数据块可以被多个实例分布式地分段master。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第21步: 在任一个实例上执行: selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_Instance" ;
从以上结果可以看到,存在大量的数据块的master实例和owner实例不是同一个实例的情况。这是可以预料到的:我们在两个实例上同时密集地OLTP同一张表!这样会有大量的实例间的通信。以下内容来自此刻的AWR报告: Top 5 Timed Events
RAC Statistics
Global Cache Load Profile
Global Cache Efficiency Percentages (Target local+remote 100%) Buffer access - local cache %:99.69 Buffer access - remote cache %:0.30 Buffer access - disk %:0.00 Global Cache and Enqueue Services - Workload Characteristics Avg global enqueue get time (ms):0.3 Avg global cache cr block receive time (ms):2.0 Avg global cache current block receive time (ms):1.4 Avg global cache cr block build time (ms):0.1 Avg global cache cr block send time (ms):0.0 Global cache log flushes for cr blocks served %:23.9 Avg global cache cr block flush time (ms):1.5 Avg global cache current block pin time (ms):0.0 Avg global cache current block send time (ms):0.0 Global cache log flushes for current blocks served %:0.2 Avg global cache current block flush time (ms):1.9 Global Cache and Enqueue Services - Messaging Statistics Avg message sent queue time (ms):0.2 Avg message sent queue time on ksxp (ms):0.8 Avg message received queue time (ms):0.0 Avg GCS message process time (ms):0.1 Avg GES message process time (ms):0.0 % of direct sent messages:73.86 % of indirect sent messages:13.11 % of flow controlled messages:13.03 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第22步: 现在让问题回到简单的状态,我们把第2个实例上的update结束。 在任一个实例上执行: selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_Instance"and "OWNER_Instance"=1;
selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_Instance"and "OWNER_Instance"=2;
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第23步: 过一会在任一个实例上执行,再查: selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_Instance"and "OWNER_Instance"=1;
selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_Instance"and "OWNER_Instance"=2;
从以上结果可以看到,当我们把第2个实例上的update结束后,第2个实例的owner计数在不断下降,但是仍然存在不少数据块的master实例和owner实例不是同一个实例的情况,这样在我们的密集OLTP应用模型下仍然存在实例间不必要的通信量。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第24步: 在任一个实例上执行: select* from v$gcspfmaster_info where object_id=52533; 没有输出 说明此刻没有发生自动Remaster(Object Affinity and Dynamic Remastering引起)。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
实验第25步: 在任一个实例上执行(可执行多次): select drms from X$KJDRMAFNSTATS;值始终为2也验证了此刻没有发生自动Remaster。 |
表5:能够查出某个块Master实例和Owner实例的X$表
5.自动Remaster(Object Affinity and Dynamic Remastering引起)和手工Remaster(oradebug命令)
实验第26步: 在任一个实例上执行: select x.ksppinm name,y.ksppstvl value from sys.x$ksppi x,sys.x$ksppcv y where x.indx=y.indx and substr(x.ksppinm,0,1)='_' and x.ksppinm like '_gc_affi%';
| ||||||||||||
下面我们来做自动remaster(Object Affinity and Dynamic Remastering引起)的实验。 实验第27步: 在任一个实例上执行: selectcount(*)from myviewwhere "OWNER_Instance" <> "MASTER_Instance" ;
在任一个实例上执行: select* from x$OBJECT_AFFINITY_STATISTICS where object=52533; 无输出,这是正常的。 x$OBJECT_AFFINITY_STATISTICS统计信息会定时清空。 | ||||||||||||
实验第28步: 在实例1上:连续做以下两条语句,直到t04209_uname表中有51200000行记录为止。 insert /*+ append */ into t04209_uname select * from t04209_uname; commit; |
转载于:https://blog.51cto.com/botang/1351715