ORA-01658创建表或索引报错分析

简介: 某项目最近在 SQL Loader 导数据时偶尔会报错,类似如下:SQL loader ORA-01658 unable to creale INITIAL extent for segment in tablespace ADS5GP2P_1这个报错的意思是,没有足够的连续空间为表或索引创建 INITIAL extent

一、报错信息

某项目最近在 SQL Loader 导数据时偶尔会报错,类似如下:

SQL loader ORA-01658 unable to creale INITIAL extent for segment in tablespace ADS5GP2P_1

这个报错的意思是,没有足够的连续空间为表或索引创建 INITIAL extent:

[oracle@node1:1 ~]$ oerr ora 1658
01658, 00000, "unable to create INITIAL extent for segment in tablespace %s"
// *Cause:  Failed to find sufficient contiguous space to allocate INITIAL
//          extent for segment being created.
// *Action: Use ALTER TABLESPACE ADD DATAFILE to add additional space to the
//          tablespace or retry with a smaller value for INITIAL

二、报错分析

数据库版本是 Oracle 11G,实际查看该表空间仍有2T多的剩余空间,根据以往经验,最大的可能是这2T多的剩余空间大多是碎片,在业务忙时无法提供足够可用的连续空间,以下做验证。
DBA_FREE_SPACE describes the free extents in all tablespaces in the database.
数据字典 DBA_FREE_SPACE 描述了所有的可用 extent 情况:

select trunc(bytes/1048576) mb, count(*)
  from dba_free_space
 where tablespace_name = 'ADS5GP2P_1'
 group by trunc(bytes/1048576)
 order by 1;
 0    2374933
 1    61526
 2    21622
 3    13995
 4    34797
 5    5133
 6    6851
 7    3687
 8    16463
 9    2883
10    1785
11    1348
12    5552
13    742
14    666
15    615
16    6029
17    326
18    300
19    398
20    2553
21    94
22    62
23    49
24    82
25    41
26    21
27    9
28    26
29    15
30    12
......

以上可见空闲的空间里有大量的碎片,可能的原因是频繁、长时间的修改、导入数据逐步导致的。这些碎片的大小达到了 2T,如下:

select tablespace_name, sum(bytes/1048576) mb
  from dba_free_space
 where trunc(bytes/1048576) < 1
 group by tablespace_name;
---
ADS5GP2P_1: 2162858.375

结论是:
虽然空闲空间很多,但是这些空闲空间大都是小于 1M 的小碎片,这些小碎片加起来达到了2T,导致可能有时没法及时分配 INITIAL extent 给应用使用,从而报错。
以下进一步确认这些碎片的具体大小:

select trunc(bytes/65536) k64, count(*)
  from dba_free_space
 where tablespace_name = 'ADS5GP2P_1'
 group by trunc(bytes/65536)
 order by 1;
 1    31756
 2    8567
 3    6803
 4    10116
 5    3230
 6    1748
 7    2027
 8    2492
 9    11143
10    4988
11    1183
12    1875
13    21457
14    43512
15    2228918
16    1251
17    151
18    152
19    230
20    177

以上可见 15*65536=960k 的 extent 达到了 2228918,合计 2T 多。
可见这些小碎片大多是 960k 的小碎片,理论上对于大多数 64k 的 INITIAL extent 是可用、不会报错的。

三、解决方案

因此最终的解决方案是,修改报错表和索引的 INITIAL extent,让他们小于多数碎片的大小,即小于 960k。这个只能在业务闲时操作,确保操作的表不要引起其他问题,比如先备份表。

目录
相关文章
|
SQL
删除SQL表数据时存在约束的解决方法
删除SQL表数据时存在约束的解决方法
203 0
|
Oracle 关系型数据库 索引
oracle查询表 索引、唯一约束、字段
oracle查询表 索引、唯一约束、字段
|
SQL Oracle 关系型数据库
Oracle 数据库SQL语句查询oracle数据库表主键,查看oracle指定表的表结构实例演示
Oracle 数据库SQL语句查询oracle数据库表主键,查看oracle指定表的表结构实例演示
239 0
Oracle 数据库SQL语句查询oracle数据库表主键,查看oracle指定表的表结构实例演示
|
SQL Oracle 关系型数据库
Oracle 数据库sql语句修改表字段的字段类型和长度
Oracle 数据库sql语句修改表字段的字段类型和长度
412 0
Oracle 数据库sql语句修改表字段的字段类型和长度
|
SQL Oracle 关系型数据库
|
Oracle 关系型数据库 索引
|
SQL Oracle 关系型数据库
|
Oracle 关系型数据库
Oracle表中含有255列以上是需要注意的(r12笔记第77天)
   今天看JL(Jonathan Lewis)的一篇文章,真是费了不少的脑细胞,玩Oracle几十年的老司机,看问题的角度和深度果然不一样,当时看他的大作《Oracle核心技术》就花了我不少时间,还没有看完,一本薄薄的书能够蕴含如此的能量,做技术到了这个火候,让人深深佩服。
1180 0