关于gc current blocks received一个特殊例子

2025-11-25Linux/AIX / Oracle / RAC

2条回复这篇文章源于和Kamus的讨论, 出现’gc current blocks received’的一种特殊情况.当select语句请求gc cr时, 为什么会出现等待事件’gc current block 2-way’, 同时’gc current blocks received’统计值增加?一个gc cr请求的出现, 常见的原因是数据块存在于其他实例的缓存中. 出现gc cr请求时, 可能会出现三种情况1. 请求的数据块不在gc中2. 请求的数据块在gc中且状态是xcur3. 请求的数据块在gc中且状态是scur以下是三种情况的描述, 测试环境 10.2.0.3.0 Linux 32bit 2-node RAC.1. 请求的数据块不在gc中 请求的session等待消息’gc cr grant 2-way’, 拿到grant之后, 开始物理读. 因为可以从数据块的地址算出对应的master, 无论RAC多少个实例, gc cr grant只会是2-way, 不会出现3-way. 以下是这种情况的sql trace片断.

1234 WAIT #34: nam='gc cr grant 2-way' ela= 145 p1=1 p2=64631 p3=1 obj#=146039 tim=1302016329430647WAIT #34: nam='db file sequential read' ela= 2072 file#=1 block#=64631 blocks=1 obj#=146039 tim=1302016329432741WAIT #34: nam='gc cr grant 2-way' ela= 111 p1=1 p2=64632 p3=1 obj#=146039 tim=1302016329432928WAIT #34: nam='db file sequential read' ela= 3026 file#=1 block#=64632 blocks=1 obj#=146039 tim=1302016329435970
  1. 请求的数据块在gc中且状态是xcur, 等待事件是’gc cr block 2-way’, ‘gc cr blocks received’统计值增加. 持有xcur的实例会负责构建CR版本, 发给请求的实例. 如果需要的话, 构建的过程会apply undo records, 可以观察到统计信息’data blocks consistent reads – undo records applied’, 或者’transaction tables consistent reads – undo records applied’的增长.3. 请求的数据块在gc中且状态是scur, ‘gc current blocks received’统计值增加, 这种情况可以解释文章开始的问题. 对于单块请求, 等待事件是’gc current block 2-way’, 对于多块请求, 等待事件是’gc cr multi block request’. RAC中因为请求CR, 从DISK中首次读出来的数据块的状态是scur, 对状态为scur的数据块, 没有被修改过的话, 每个实例持有的状态都是scur. 数据块的holder是否等于master, 不会影响这种等待事件和统计信息. 以下验证过程.1. 建表T, 插入1000行到1000个数据块
12345678910111213141516171819202122232425262728 create table t(id number,small_vc number,padding varchar2(1000))pctfree 99pctused 1/ insert into tselect rownum id, lpad(rownum,10,'0') small_vc, rpad('x',100) paddingfrom dualconnect by level <= 1000; commit; alter table t add constraint t_pk primary key(id); begindbms_stats.gather_table_stats(user,'T');end;/

表T所有数据块都在文件1上, 分布在三个区间 [63825, 63873 + 7], [64137, 64201 + 7], [64265, 65033 + 127]

123456789101112131415161718192021222324252627282930313233343536373839404142434445 sys@V10> col owner for A3sys@V10> col segment_name for A2sys@V10> select 2 owner, 3 segment_name, 4 segment_type, 5 extent_id, 6 file_id, 7 block_id, 8 blocks 9 from 10 dba_extents 11 where 12 segment_name = 'T' 13 and owner = 'SYS' 14 order by extent_id 15 / OWN SE SEGMENT_TYPE EXTENT_ID FILE_ID BLOCK_ID BLOCKS— — —————— ———- ———- ———- ———-SYS T TABLE 0 1 63825 8SYS T TABLE 1 1 63833 8SYS T TABLE 2 1 63841 8SYS T TABLE 3 1 63849 8SYS T TABLE 4 1 63857 8SYS T TABLE 5 1 63865 8SYS T TABLE 6 1 63873 8SYS T TABLE 7 1 64137 8SYS T TABLE 8 1 64145 8SYS T TABLE 9 1 64153 8SYS T TABLE 10 1 64161 8SYS T TABLE 11 1 64169 8SYS T TABLE 12 1 64177 8SYS T TABLE 13 1 64185 8SYS T TABLE 14 1 64193 8SYS T TABLE 15 1 64201 8SYS T TABLE 16 1 64265 128SYS T TABLE 17 1 64393 128SYS T TABLE 18 1 64521 128SYS T TABLE 19 1 64649 128SYS T TABLE 20 1 64777 128SYS T TABLE 21 1 64905 128SYS T TABLE 22 1 65033 128 23 rows selected.

通过block address, 可以从x$kjbl查询表T的所有数据块对应的owner和master, 都是从0开始算起. 以下查询观察表T中, 数据块对应的owner和master

123456789101112131415 select kjblowner, kjblmaster, count(*)from x$kjblwhere to_number(substr ( kjblname2, instr(kjblname2,',')+1, instr(kjblname2,',',1,2)-instr(kjblname2,',',1,1)-1)/65536) = 1and (to_number(substr ( kjblname2, 1, instr(kjblname2,',')-1)) between 63825 and 63873 + 7 or to_number(substr ( kjblname2, 1, instr(kjblname2,',')-1)) between 64137 and 64201 + 7 or to_number(substr ( kjblname2, 1, instr(kjblname2,',')-1)) between 64265 and 65033 + 127)group by kjblowner, kjblmaster/

观察表T的数据块在缓存中的状态和数量.

1234567891011 select objd, status, count(*)from v$bhwhere objd = &t_obj_idgroup by objd, statusorder by count(*);
  1. instance 2, flush buffer_cache, 清空两个instance的缓存.
123 sys@V10> alter system flush buffer_cache; System altered.
  1. instance 2, 通过oradebug lkdebug -m pkey 指定T的master node是instance 2. 接着在instance 1读出所有的数据块, 然后在instance 2向instance 1请求’gc cr’, 这时表T1000的数据块的holder=instance 1, master = instance 2, holder不等于master, 观察两个instance请求前后统计信息的变化.
12345678 sys@V10> oradebug lkdebug -m pkey &t_obj_idStatement processed. sys@V10> select * from v$gcspfmaster_info where object_id=&t_obj_id; FILE_ID OBJECT_ID CURRENT_MASTER PREVIOUS_MASTER REMASTER_CNT———- ———- ————– ————— ———— 0 146039 1 0 0
  1. instance 1, 索引扫描T, isntance 1的buffer cahce中有1000个状态为scur数据块, x$kjbl显示1000相应的shadow resource, 因为master是instance 2, gc remote grants和gcs message sent是1000.
123456789101112131415161718192021222324252627282930 sys@V10> select /*+ index(t)*/ 2 max(small_vc) 3 from 4 t 5 where 6 id > 0 7 ; MAX(SMALL_VC)————- 1000 –query v$bh OBJD STATUS COUNT(*)———- ——- ———- 146039 cr 1 146039 scur 1000 146039 free 1820 –query v$kjbl KJBLOWNER KJBLMASTER COUNT(*)———- ———- ———- 0 1 1000 –session statisticsName Value—- —–gcs messages sent 1,000gc local grants 3gc remote grants 1,000
  1. instance 2, 索引扫描T, 观察两个instance统计信息的变化
1234567891011121314151617 a. instance 1, 'gc current blocks served'增加1003, v$bh和x$kjbl中表T的信息没变.–system statisticsName Value—- —–gc current blocks served 1,003 –query v$bh OBJD STATUS COUNT(*)———- ——- ———- 146039 cr 1 146039 scur 1000 146039 free 1812 –query v$kjbl KJBLOWNER KJBLMASTER COUNT(*)———- ———- ———- 0 1 1000

b. instance 2, ‘gc current blocks received’增加1003, 验证了’gc cr’的请求也会使’gc current blocks received’增加.

1234 –session statisticsName Value—- —–gc current blocks received 1,003

c. instance 2, 1000个状态为scur的buffer, 因为instance 2是master, x$kjbl分别显示instance1/2上的1000个resource.

1234567891011 –query v$bh OBJD STATUS COUNT(*)———- ——- ———- 146039 scur 1000 146039 free 1878 –query v$kjbl KJBLOWNER KJBLMASTER COUNT(*)———- ———- ———- 1 1 1000 0 1 1000

e. instance 2, sql trace显示扫描过程等待’gc current block 2-way’ 1003次.

1234 WAIT #2: nam='gc current block 2-way' ela= 237 p1=1 p2=65122 p3=1 obj#=146039 tim=1302120511468699WAIT #2: nam='gc current block 2-way' ela= 240 p1=1 p2=65123 p3=1 obj#=146039 tim=1302120511468992WAIT #2: nam='gc current block 2-way' ela= 258 p1=1 p2=65124 p3=1 obj#=146039 tim=1302120511469288WAIT #2: nam='gc current block 2-way' ela= 257 p1=1 p2=65125 p3=1 obj#=146039 tim=1302120511469584

想把RAC cache fusion所有的行为想到罗列出来我想比较困难, block class有18中, 各种状态xcur/scur/pi/cr…, 每种的处理方法都是否一样, gc中的buffer是否dirty, 是否被ping住? 不过了解 cache fusion的基本原理之后, 针对特定的情况, 我们可以可以设计实验进行验证.

12345678910111213141516171819202122232425 sid@V10> select * from v$waitstat 2 / CLASS COUNT TIME—————— ———- ———-data block 1212 525sort block 0 0save undo block 0 0segment header 4 1save undo header 0 0free list 0 0extent map 0 01st level bmb 142 502nd level bmb 235 813rd level bmb 236 55bitmap block 0 0bitmap index block 0 0file header block 0 0unused 0 0system undo header 0 0system undo block 0 0undo header 16 0undo block 13 1 18 rows selected.

2010-09-22 黄昏, 人们在托林寺转经[](https://lh4.googleusercontent.com/-6JBDNlcNjVE/T3xfbGofwgI/AAAAAAAAYwI/XK27j8V3x-M/s1440/DSC_2879.JPG)本条目发布于2012年4月4日。属于Oracle分类,被贴了gc crgc current标签。### 文章导航 ORA-04030 and UTL_FILE.Get_LineSLOB: 有趣的IO测试工具 ## 《关于gc current blocks received一个特殊例子》上有2条评论

1756815188527-34da662a-89fd-4603-b080-f74f5f2e6c0f.png

电子邮件地址不会被公开。必填项已用*标注姓名*电子邮件*站点评论您可以使用这些HTML标签和属性:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>