1. 首页
  2. IT资讯

RAC中的enq: TS等待

前段时间DW系统切换到RAC集群时,出现了严重的enq: TS问题。[@more@]这次问题的现象是原来运行正常的任务忽然变得很慢,分析执行计划后发现是因为执行计划出错,SQL走笛卡尔连接消耗了大量的临时表空间,从而引起了enq: TS等待。这次问题的直接解决方法就是修复执行计划,避免笛卡尔连接,但是仅仅这样做的话,还是存在风险。因为这个问题的根本原因是因为对临时表空间的大量消耗导致,如果以后有超大数据量的计算,那么不可避免需要大量的临时表空间,这个时候,enq: TS也就无法避免了。不过这个问题只在rac出现,单实例不会出现这种问题。这个等待事件容易出现在一个SQL在一个节点消耗大量临时表空间,导致临时表空间分配非常不均衡的情况。在RAC中,当一个会话需要临时段时,会从temp extent pool中申请,当一个temp extent被一个节点的会话申请后,其他节点看不到也不能使用这些临时段;当一个节点把自己节点所属的临时段用完后,会请求从temp extent pool继续申请;如果pool中已经没有可用的temp extent,则Oracle会请求其他节点释放状态是free的extent到pool中。而一般来说,每一次申请每个节点最多释放100个extent,在等待释放时,我们可以看到enq: TS – contention等待。在数据仓库中,这个回收速度根本跟不上消耗速度。当用完后会继续上述的申请过程,从而我们会长时间看到enq: TS – contention等待。要解决这个问题,我们可以让系统尽快释放free状态的extent到pool中,避免在需要时才回收。Oracle提供了一个命令可以快速回收temp extent:alter session set events ‘immediate trace name DROP_SEGMENTS level N’;其中:N为临时表空间对应的TS#+1。这个命令执行一次,就在一个节点释放100个extent,因此,可能需要循环多次执行。下面这个过程把上面的命令封装了一下:PROCEDURE P_RELEASE_TEMP_SEG(P_GB NUMBER DEFAULT 50) IS L_RELEASE_SQL VARCHAR2(256); L_LOOP NUMBER; L_KEEP_GB NUMBER := 10; –keep 10GB ,don’t release L_SESSION_COUNT NUMBER;–active session count L_SESSION_THRETHOLD NUMBER:=20; L_START_DATE DATE:=SYSDATE; /* 定期把某个节点free的temporary segment释放到temporary segment pool,避免enq: TS contention问题 保留10GB空间不release,避免小temp空间需求频繁从temporary segment pool中申请资源 */ BEGIN FOR C_TEMP_SEG IN (SELECT T1.TS#, S.TABLESPACE_NAME, S.USED_EXTENTS, S.FREE_EXTENTS, S.CURRENT_USERS, S.FREE_BLOCKS, T2.NEXT_EXTENT, T2.BLOCK_SIZE, ROUND(S.FREE_BLOCKS * T2.BLOCK_SIZE / 1024 / 1024 / 1024, 2) FREE_GB, ROUND(S.USED_BLOCKS * T2.BLOCK_SIZE / 1024 / 1024 / 1024, 2) USED_GB FROM V$SORT_SEGMENT S, V$TABLESPACE T1, DBA_TABLESPACES T2 WHERE T2.CONTENTS = ‘TEMPORARY’ AND T1.NAME = T2.TABLESPACE_NAME AND S.TABLESPACE_NAME = T2.TABLESPACE_NAME AND S.FREE_BLOCKS * T2.BLOCK_SIZE / 1024 / 1024 / 1024 > P_GB) LOOP L_LOOP := FLOOR((C_TEMP_SEG.FREE_GB – L_KEEP_GB) / (100 * C_TEMP_SEG.NEXT_EXTENT / 1024 / 1024 / 1024)); L_RELEASE_SQL := ‘ alter session set events ”immediate trace name DROP_SEGMENTS level ‘ || TO_CHAR(C_TEMP_SEG.TS# + 1) || ””; SELECT COUNT(1) INTO L_SESSION_COUNT FROM V$SESSION S WHERE STATUS=’ACTIVE’ AND S.PADDR NOT IN (SELECT BP.PADDR FROM V$BGPROCESS BP WHERE BP.PADDR<>’00’) ; IF L_SESSION_COUNT

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/231499/viewspace-1047693/,如需转载,请注明出处,否则将追究法律责任。

主题测试文章,只做测试使用。发布者:布吉卡,转转请注明出处:http://www.cxybcw.com/195657.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code