10.15.08

rac下的TS enq解决方案–适用于rac数据仓库环境

Posted in Oracle at 2:00 下午 由 wanghai

公司里面有一个12nodes的rac环境来跑数据仓库的应用,有一个1TB的临时表空间,有一些应用会跑的很慢,比如多个大表关联,而且有复杂的分组排序的操作会耗费大量的临时表空间,这些应用有事会跑的比较快,有时会跑的莫名其妙的慢,这是为什么呢?

花了点时间看了一下原因,
模块1正常的时候15分钟完成,但是慢的时候会跑1个半小时,原来有些的P0XX进程都在等待”enq: TS – contention”,根据gv$session_wait我们可以通过p2找到tablespace ID,进而可以发现是临时表空间出现了TS enq,然后可以发现是smon进程持有了这enq,这些P0XX的并行进程都在等待smon去释放这个enq,但是smon这时候在做什么呢?
那首先让我们来看一下rac里面的temp空间分配的机制是怎么样的。在rac里面,大家都知道temp表空间对所有节点都是可见的,但是temp空间一旦分配给了某一个节点使用,其他节点对这部分空间将都会看不见。

很典型的情况就像下面这样,每个节点有自己的temp extent

INST_ID    TSNAME  TOTAL   USED FREE
---------- ------- -----   ---- -----
         1 TEMP     6678   0     6678
         2 TEMP    83966   0    83966
         3 TEMP     8908   0     8908
         4 TEMP     1589   0     1589
         5 TEMP    10006   0    10006
         6 TEMP    12147   0    12147
         7 TEMP       99   0       99
         8 TEMP      414   0      414
         9 TEMP    10913   0    10913
        10 TEMP     2347   6     2341
        11 TEMP      343   3      340
        12 TEMP    16189   0    16189

一旦某个节点上发生了一个大的分组排序的操作,它目前分配到的temp exten将会被耗尽,这时候它会发出一个Cross Instance Call(CIC)来向每个节点请求新的temp extent,这时候smon就启动去回收每个节点的free temp extent,在这个过程中smon会持有TS enq,发起空间请求的节点必须等待smon完成对所有节点的free temp extent回收请求后才会继续下一步动作,smon每次向每个节点回收100 extents的临时空间,在这个12nodes的环境里面最大就是1200 extents,每个extent设置为8M,大致每次回收8GB的空间可以给发起节点使用,但是在一个很大操作面前,8GB的临时空间一下子就能用完。而且在一个多并发的系统里面,同时会有很多个大操作在进行,这个时候对于临时表空间的争用将会非常严重,会严重影响整个系统的执行效率。

下面来看一个实验
首先看一下当前系统个节点临时空间的分配情况

INST_ID    TSNAME  TOTAL USED FREE
---------- ------- ----- ----- ---
         1 TEMP    6378  0    6378
         2 TEMP   82296  0   82296
         3 TEMP    8908  0    8908
         4 TEMP    1589  0    1589
         5 TEMP   10006  0   10006
         6 TEMP   12147  0   12147
         7 TEMP      99  0      99
         8 TEMP     414  0     414
         9 TEMP   10913  0   10913
        10 TEMP    2347  6    2341
        11 TEMP     520  3     517
        12 TEMP   16189  0   16189

我们可以看到7节点上当前只分配到了99个extents,

select sum(TOTAL_EXTENTS)*8/1024||'G' from gv$sort_segment;

SUM(TOTAL_EXTENTS)*8/1024||'G'
-----------------------------------------
1185.984375G

当前系统总共分配了1185.984375G的temp空间,总的temp表空间大小是1200G,整个系统里面还有1200-1186=14GB的空闲temp空间可以使用

下面登录到7节点执行一个耗费临时空间的操作

dwdb7>  exec big_sort(null);

过了一会可以看到

select sum(TOTAL_EXTENTS)*8/1024||'G' from gv$sort_segment;
SUM(TOTAL_EXTENTS)*8/1024||'G'
-----------------------------------------
1199.9921875G

系统的空闲临时空间已经被用完,这个时候7节点会通过CIC请求smon释放其他节点的空闲temp空间,可以看到节点7现在的等待

Taobao@dwdb7> /

EVENT
----------------------------------------------------------------
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
PX Deq Credit: send blkd
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention
enq: TS - contention

再看各节点temp空间的分布

Taobao@dwdb9> select INST_ID,TABLESPACE_NAME TSNAME,
TOTAL_EXTENTS TOTAL,USED_EXTENTS USED,FREE_EXTENTS
FREE from gv$sort_segment order by inst_id;

   INST_ID    TSNAME  TOTAL   USED  FREE
---------- --------------- ----------
         1 TEMP    6278      0   6278
         2 TEMP   82196      0  82196
         3 TEMP    8808      0   8808
         4 TEMP    1489      0   1489
         5 TEMP    9906      0   9906
         6 TEMP   12047      0  12047
         7 TEMP    2992   2992      0
         8 TEMP     314      0    314
         9 TEMP   10813      0  10813
        10 TEMP    2247      3   2244
        11 TEMP     420      3    417
        12 TEMP   16089      0  16089

smon完成一轮空间回收,节点7继续进行排序操作,但是可以看到所有的其他节点free_extents都少了100

  INST_ID   TSNAME  TOTAL  USED  FREE
---------- -------------------------
         1 TEMP   6178     0    6178
         2 TEMP  82096     0   82096
         3 TEMP   8708     0    8708
         4 TEMP   1389     0    1389
         5 TEMP   9806     0    9806
         6 TEMP  11947     0   11947
         7 TEMP   3728  3728       0
         8 TEMP    214     0     214
         9 TEMP  10713     0   10713
        10 TEMP   2147     3    2144
        11 TEMP    320     3     317
        12 TEMP  15989     0   15989

然后节点7用完smon回收的空间后又会碰到空间不够的问题,于是发起CIC请求smon会继续回收,

INST_ID    TSNAME   TOTAL    USED    FREE
---------- ------  -------- -------------
         1   TEMP     6078     0      6078
         2   TEMP    81996     0     81996
         3   TEMP     8608     0      8608
         4   TEMP     1289     0      1289
         5   TEMP     9706     0      9706
         6   TEMP    11847     0     11847
         7   TEMP     5192  5192         0
         8   TEMP      114     0       114
         9   TEMP    10613     0     10613
        10   TEMP     2047     3      2044
        11   TEMP      220   117       103
        12   TEMP    15889     0     15889

周而复始,直到整个操作完成,这中间的回收过程会比较久,而且排序操作会一直等待smon从而影响整个应用模块的时间,而且由于各个节点分配到的temp extent严重贫富不均,如果一个sql刚好分配到了某个temp extent比较少的节点,它将会深受其害。

问题的原因相信大家都看明白了,下面就来看一下解决的方案,Oracle提供了一个命令来释放temp空间

ALTER SESSION SET events ‘immediate trace name drop_segments level tablespace_number+1′;

现在节点1有5478个free temp extent,


 INST_ID    TSNAME   TOTAL       USED        FREE
---------- ---------- --------  ---------- -------
         1      TEMP         5478            0         5478
 

登录到节点1执行两次ALTER SESSION SET events ‘immediate trace name drop_segments level 4′后将会释放出200个extent

INST_ID    TSNAME   TOTAL       USED        FREE
---------- ---------- --------  ---------- -------
         1      TEMP         5278            0         5278

这样的话我们就可以自己包装到crontab,定时在每个节点执行这个命令,这样节点间贫富不均的情况将会被修正,各个节点的空闲temp空间将会被及时的返回到temp pool中供需要的节点使用,也就避免了sql会去等待smon回收,基本上相当于每个节点有自己的专属的temp空间的效果,修正了RAC在temp空间管理这块的缺陷。

16 条评论 »

  1. Fenng said,

    十月 15, 2008 at 3:05 下午

    赞!

    好久不更新了阿,更新果然有好帖

  2. wanghai said,

    十月 15, 2008 at 5:01 下午

    最近比较空,就看一下系统本身的问题,
    调整了很多东西,懒得一个一个写

  3. 棉花糖ONE said,

    十月 15, 2008 at 7:21 下午

    学习,very good

  4. kamus said,

    十月 17, 2008 at 2:06 上午

    如果使用temp tablespace group的话,情况会有所改善吗?

  5. wanghai said,

    十月 17, 2008 at 9:20 上午

    kamus,Note:459036.1能解答你的问题

  6. bartholo said,

    十月 21, 2008 at 11:08 上午

    很牛,受教了。经常更新blog啊,呵呵

  7. banky said,

    十月 27, 2008 at 4:47 下午

    md,哎,就跟我上次看星光大道一样!!!那个修车工,大家都说他不做歌星太浪费了!!
    你说你是不是也太浪费了啊。。。

  8. vogts said,

    十月 30, 2008 at 3:45 下午

    学习了。此外,这个blog,终于更新了。

  9. yeka said,

    十一月 6, 2008 at 8:37 下午

    七公,好久不见!

    在西毒的博客上看到这条新闻,很开心,如果在杭州,咱们该一起喝一杯咯:)

    听说已经升级了(还是准升级?),祝福!

    我的博客搬家了。

    常联系,我经常在gtalk上。

  10. yeka said,

    十一月 6, 2008 at 8:38 下午

    http://www.flickr.com/photos/fenng/3003661069/

    就是这条新闻,刚才忘记放了。

  11. netbanker said,

    十二月 20, 2008 at 6:12 上午

    very nice article

  12. yeka said,

    十二月 31, 2008 at 10:38 下午

    msn上抓不到你,只好这里道声新年快乐了!知道肯定是忙儿子去了…….

    俺的博客地址,要不给换这个链接:yeka.blogbus.com

  13. jlttt said,

    一月 3, 2009 at 11:24 上午

    select sum(TOTAL_EXTENTS)*8/1024||’G’ from gv$sort_segment;

    SUM(TOTAL_EXTENTS)*8/1024||’G’
    —————————————–
    1185.984375G
    当前系统总共分配了1185.984375G的temp空间

    这段没整明白。

  14. testmvb said,

    四月 15, 2009 at 5:21 下午

    好厉害的七公,发现差距了

  15. coolfuyue said,

    六月 25, 2009 at 10:09 上午

    你好,真的学习了啊 佩服!
    对了,可以给我一个CNOUG论坛的邀请码吗?很喜欢这个论坛 谢谢

    我的邮箱:coolfuyue@163.com

  16. P.Linux said,

    九月 30, 2009 at 5:05 下午

    七公很低调呀,宣讲会之前只知道淘宝的Ningoo和Piner大牛,还不知道七公~哈哈~
    把七公的博客也收进GoogleReader,HASH JOIN/MERGE JOIN/NESTED LOOP JOIN回来查过了,又多了解一些机制。
    水平还是有点问题,继续努力提高~

留下评论