已索引

该文章已被如下文章引用:

故障描述

EDI 跑数做拉链表运行如下语句时报错 ORA-1653 错误。
INSERT into X SELECT …… [GROUP BY ……];

在数据库 alert 日志中也看到相关的报错信息如下:

Mon Dec 25 03:57:18 2023
ORA-1652: unable to extend temp segment by 8 in tablespace   TBS_HSDM_DATA

Mon Dec 25 04:18:44 2023
ORA-1653: unable to extend table EDI.F_NHX_KNA_DPAC_HL by 64 in    tablespace TBS_CFOP_DATA 
ORA-1653: unable to extend table EDI.F_NHX_KNA_DPAC_HL by 4096 in   tablespace TBS_CFOP_DATA 

使用 oerr 命令可以查看到,这儿的数字是指 blocks。如 8 代表 8个 blocks。
另外,注意这儿的 TBS_CFOP_DATA 表空间是永久表空间,并非临时表空间。
这儿的 ORA-1652 报错跟语句中的 group by 没有关系(实际上并没有 group by 语句,这儿写出来只是为了对其引起注意)。

那现在就有两个问题:

  1. 报错中为什么是 "temp segment"?
  2. TBS_CFOP_DATA 表空间空间是否充足?

为什么是 "temp segment"?

在 Doc ID 94178.1 (ORA-01652: in Tablespace Other than Temporary During ALTER INDEX REBUILD) 中,提到重建索引的过程中会用到两种临时段:

During an index rebuild, there are two types of temporary segments involved.

First, there are the temporary segments that are used to store partial sort data when the SORT_AREA_SIZE is too small to process the complete sort set. These segments are built in the user's default TEMPORARY tablespace.

Second, as the index is being rebuilt, it uses a segment which is defined as a temporary segment until the rebuild is complete. Once this segment is fully populated, the old index can be dropped and this temporary segment is redefined
as a permanent segment with the index name.

The error you are seeing is probably due to there being insufficient room in the index's tablespace to hold both the original index and the new version concurrently. The new version of the index, currently a temp segment, will be in the tablespace where the index is required.

使用第二种临时段的还有如下一些操作:
create index
create tables ... as select ...
insert into ... as select ....
create pk constraint
enable constraint
move table

表空间 TBS_CFOP_DATA 为什么空间不足?

下面查看下 TBS_CFOP_DATA 表空间当前的 free 空间大小:

select sum(bytes)/1024/1024/1024 as "size(G)"
from dba_free_space 
where tablespace_name = 'TBS_HSDM_DATA';

   size(G)
----------
200.732361

看一下这些 free 空间的分布情况:

SQL> select FILE_ID,sum(BYTES)/1024/1024/1024 as "SIZE(G)" 
from  dba_free_space t  
where TABLESPACE_NAME='TBS_CFOP_DATA' 
group by FILE_ID;

   FILE_ID    SIZE(G)
---------- ----------
       325 11.2111816
        13 19.8383789
        14 17.0698853
        20 17.4968262
        17 23.6897583
       301 15.6937256
        18 19.7184448
        15  22.697937
        16 19.2509155
        19 24.0870361
       324 9.97827148

12 rows selected.

可以发现每个数据文件都有较大的剩余空间。

再来用平时查询表空间使用率的语句来看一下该表空间的剩余大小:

TABLESPACE_NAME                  TOTAL_MB    USED_MB USED_PCT                                     FREE_MB
------------------------------ ---------- ---------- ----------------------------------------- ----------
TBS_HSDM_DATA                      419840 214290.063 51.04%                                    205549.938

可见表空间的剩余空间是很大,一般说来,不应该出现空间不足的问题。

那问题出现在哪儿呢?上面的查询只是查询的总剩余空间是否足够,但是表空间是存在碎片的,上面free空间的总值是由很多不连续的空间组成的。

我们看一下为该表分配区的历史记录:

SQL> select EXTENT_ID,BYTES/1024/1024 MB from dba_extents where SEGMENT_NAME='F_NHX_KNA_DPAC_HL' order by EXTENT_ID

 EXTENT_ID         MB
---------- ----------
         0       .125
         1      .0625
……
        14      .0625
        15          1
……
        77          1
        78          8
……注意并不是说会越来越大,中间出现的数字有2,52,64,43,21,2,64,32,7,24.5 等
……所谓的自动分配,就是完全由 Oracle 来决定是单 extent 的大小

       529         64
……
       660         64

661 rows selected.

可见,该表空间使用的是区大小自动管理的方式,大需要大量空间时,Oracle 分配 extent 时已经趁向一个 extent 64M 了(extent 是 oracle 最小的分配单位)。

DBA_FREE_SPACE describes the free extents in all tablespaces in the database.
我们看一下该表空间最大的一个 free 空间的大小:

select max(bytes)/1024/1024/1024 as "size(G)"
from dba_free_space 
where tablespace_name='TBS_CFOP_DATA';
 
   size(G)
----------
.001586914

大小只有1M多,Oracle 尝试分配 64M 的 extent时,出现 ORA-1652。

增加一个新的数据文件后,重新跑批后,该表空间最大的一个 free 空间的大小为:

SQL> select max(bytes)/1024/1024/1024 as "size(G)"
     from dba_free_space
     where tablespace_name='TBS_CFOP_DATA';

   size(G)
----------
.936523438

解决办法

-- By 许望(RHCA、OCM、VCP)
最后修改:2024 年 05 月 24 日 05 : 42 PM
如果觉得我的文章对你有用,请随意赞赏