昨天晚上例行程序发布,同时有一个创建索引的脚本。
而在发布的时候,创建索引报了ORA-01652: unable to extend temp segment by 128 in tablespace TEMP1错误。
在看到这个错误的时候,以为临时表空间不够了。而我们的临时表空间采用的表空间组,配有TEMP1,TEMP2,2个临时表空间
每个临时表空间有24G的空间,总共是48G的临时空间。不应该出现不够的情况。
在监控的过程中发现,重建索引只用到了TEMP1表空间,而没有充分利用到TEMP2表空间。
在用完TEMP1 24G的空间后,SQL抛出了ORA-01652错误。
后来检查了一下索引创建脚本,创建索引没开启并行,串行创建索引无法同时利用到2个临时表空间。
后来通过开启并行后,索引创建成功。
因此很多时候不要以为遇到ORA-01652就认为是空间不够了。
这个例子可以模拟如下:
SQL> show user
USER is "TEST"
SQL> select temporary_tablespace from user_users;
TEMPORARY_TABLESPACE
-----------------------------------
TEMPGRP
SQL> select * from dba_tablespace_groups;
GROUP_NAME TABLESPACE_NAME
--------------- --------------------
TEMPGRP TEMP1
TEMPGRP TEMP2
SQL> select tablespace_name,sum(bytes)/1024/1024/1024
2 from dba_temp_files where tablespace_name in ('TEMP1','TEMP2') and status='AVAILABLE'
3 group by tablespace_name;
TABLESPACE_NAME SUM(BYTES)/1024/1024/1024
-------------------- -------------------------
TEMP2 8
TEMP1 8
每个临时表空间的大小为8G,一共是16G,并且设置为非自动扩展的。
SQL> SELECT SEGMENT_NAME, BYTES/1024/1024/1024
2 FROM USER_SEGMENTS WHERE SEGMENT_TYPE='INDEX' AND SEGMENT_NAME='IDX_TEST_08';
SEGMENT_NAME BYTES/1024/1024/1024
-------------------- --------------------
IDX_TEST_08 14.2896118
我找了一个大约14G的索引,以便模拟错误。
开启一个SESSION 1:
执行重建索引的命令:
ALTER INDEX IDX_TEST_08 REBUILD;
在重建的过程中开启另外一个SESSION临时临时表空间使用率的监控:
SESSION 2:
SQL> SELECT USERNAME,TABLESPACE,BLOCKS*8192/1024/1024/1024 "TEMPUSAGE" FROM V$TEMPSEG_USAGE;
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 2.14453125
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 3.15234375
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.91210938
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.92773438
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.93945313
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.98535156
在临时表空间用到8G的时候SESSION 1的索引重建SQL就报错了:
SQL> ALTER INDEX IDX_TEST_08 REBUILD;
ALTER INDEX IDX_TEST_08 REBUILD
*
ERROR at line 1:
ORA-01652: unable to extend temp segment by 128 in tablespace TEMP1
Elapsed: 00:08:05.57
在整个重建过程中仅仅用到了TEMP1这个临时表空间,而没有用到临时表空间TEMP2.
如果开启并行的方式来重建索引,那么就可以充分利用到TEMP2临时表空间。
如下:
SESSION 1:
SQL> ALTER INDEX IDX_TEST_08 REBUILD PARALLEL 2;
SESSION 2:
可以看到已经利用到了TEMP2表空间。
SQL> SELECT USERNAME,TABLESPACE,BLOCKS*8192/1024/1024/1024 "TEMPUSAGE" FROM V$TEMPSEG_USAGE;
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 .13671875
TEST TEMP2 .051757813
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 .984375
TEST TEMP2 1.20605469
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.55761719
TEST TEMP2 7.84082031
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.55761719
TEST TEMP2 7.84082031
SQL> /
USERNAME TABLESPACE TEMPUSAGE
---------- -------------------- ----------
TEST TEMP1 7.55761719
TEST TEMP2 7.84082031
在SESSION 2:最终看到了索引创建成功了。
SQL> ALTER INDEX IDX_TEST_08 REBUILD PARALLEL 2;
Index altered.
因此表空间组在并行的情况下才能充分利用。