问题现象:
测试库使用如下方式创建索引:
create index IDX_ANA_OFFICE on ANA (OFFICE_CITY, OFFICE_NO)
tablespace IDX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 128K
next 128K
minextents 1
maxextents unlimited
pctincrease 0
);
报错:ORA-01654: unable to extend index GALT.IDX_OFFICE by 128 in tablespace IDX
改为默认创建:
create index IDX_ANA_PNR_OFFICE on ANA (OFFICE_CITY, OFFICE_NO)
tablespace IDX;
查看SQL是:
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
问题追查:
1、首先针对1654这个报错,MOS是这样介绍的:
Error: ORA-01654
Text: unable to extend index %s.%s by %s in tablespace %s
-------------------------------------------------------------------------------
Cause: Failed to allocate extent for index segment in tablespace.
Action: Use the ALTER TABLESPACE ADD DATAFILE statement to add one or more
files to the specified tablespace (1)、针对表空间不足的情况,建议使用DBA_FREE_SPACE视图进行查询(Note: 121259.1提供了若干脚本)。
(2)、另外,针对索引的问题,DBA_INDEXES视图则描述了下一个分区(NEXT_EXTENT)的大小,以及所有索引的百分比增长(PCT_INCREASE)。“next_extent”指的是试图分配的区大小(也就是报错中涉及的内容)。
区分配计算:next_extent = next_extent * (1 + (pct_increase/100))
在Concept中描述了为段分配区的算法
How Extents Are Allocated
MOS也提出了若干可能的解决方法:
Possible solutions:
------------------
- Manually coalesce adjacent free extents:
ALTER TABLESPACE
The extents must be adjacent to each other for this to work.
- Add a datafile:
ALTER TABLESPACE
- Resize the datafile:
ALTER DATABASE DATAFILE '
- Enable autoextend:
ALTER DATABASE DATAFILE '
MAXSIZE UNLIMITED;
- Defragment the Tablespace
- Lower "next_extent" and/or "pct_increase" size:
ALTER
pctincrease
下面这句话我认为是重点:
“这个错误并未指出表空间中是否有足够的空间,仅仅说明Oracle不能找到一个足够大的连续空间用来匹配next extent。
2、另一篇文章“TROUBLESHOOTING GUIDE (TSG) - UNABLE TO CREATE / EXTEND Errors”说明了各种关于“UNABLE TO CREATE / EXTEND”的错误。
“unable to extend"的错误是指当没有足够连续的空间用来分配段的情况。
I. 提出了解决这种错误所需要的信息:
(1)、判断报错表空间中最大的连续空间是多少。
SELECT max(bytes) FROM dba_free_space WHERE tablespace_name = '
这个SQL返回的是表空间最大允许的连续块大小。(DBA_FREE_SPACE不会返回临时表空间的信息,可以参考“DBA_FREE_SPACE Does not Show Information about Temporary Tablespaces (文档 ID 188610.1)”这篇文章会介绍如何查看临时表空间的连续块大小)。
如果在这个报错之后立即执行上述SQL,则返回的表空间中连续的最大块会小于这个对象正在试图分配的next extent的空间。
(2)、判断NEXT_EXTENT大小。
a) 对于PCT_INCREASE=0的字典管理表空间(DMT)或者使用统一UNIFORM区管理的本地管理表空间(LMT),使用如下SQL:
SELECT NEXT_EXTENT, PCT_INCREASE
FROM DBA_SEGMENTS
WHERE SEGMENT_NAME =
AND SEGMENT_TYPE =
AND OWNER =
AND TABLESPACE_NAME =
其中segment_type会展示在错误信息中,可能包含如下类型的segment:
CLUSTER
INDEX
INDEX PARTITION
LOB PARTITION
LOBINDEX
LOBSEGMENT
NESTED TABLE
ROLLBACK
TABLE
TABLE PARTITION
TYPE2 UNDO
TYPE2 UNDO (ORA-1651)
同样地,segment_name可以在错误信息中找到。
b) 对于使用SYSTEM|AUTOALLOCATE区管理的本地管理表空间(LMT)。
没有方法可以查询它的next extent大小。只能查询错误信息,错误信息中的块数乘以表空间的块大小,以此来判断需要创建的区大小。
c) 对于PCT_INCREASE>0的字典管理表空间(DMT)。
SELECT EXTENT_MANAGEMENT FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = '
使用如下公式计算需要分配的区大小:
extent size = next_extent * (1 + (pct_increase/100)
例如:
next_extent = 512000
pct_increase = 50
next extent size = 512000 * (1 + (50/100)) = 512000 * 1.5 = 768000
注意:
ORA-01650 Rollback Segment
pct_increase仅用于Oracle若干早期版本,后面版本中回滚段的pct_increase默认是0。
ORA-01652 Temporary Segment
临时段与表空间创建的存储默认值相同。
如果查询出现错误,则需要判断这个查询语句是否尽可能地最优以完成排序。
相关阅读:
(3)、判断表空间是否包含了AUTOEXTENSIBLE,并已经达到MAXSIZ。
对于数据文件:
SELE