惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
I
InfoQ
U
Unit 42
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
月光博客
月光博客
D
Docker
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
V
Visual Studio Blog
博客园 - 聂微东
A
About on SuperTechFans
腾讯CDC
Jina AI
Jina AI
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
博客园 - 【当耐特】
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence

博客园 - likingzi

数据库IO性能优化思考 RAID10和RAID5性能对比测试 迁移MySQL数据到Oracle实践记录 瀚高数据库不同版本对实例级用户的支持情况 使用benchmarksql测试数据库处理能力 BigCloud Enterprise Linux 8和Rocky Linux 8升级OpenSSH步骤 【翻译】凝视深渊:千核并发控制的评估 NFS使用TrueNAS SCALE的好处 linux 手动释放内存 linux8安装oracle 11g遇到的问题记录 ARM架构鲲鹏主机BClinux离线安装docker步骤 MySQL PXC 集群死锁分析案例 记录一下oracle 19c的集群节点移除、新增操作 MySQL PXC集群多个节点同时大量并发update同一行 MongoDB集群同步 【最佳实践】MySQL数据库迁移到PXC集群 MySQL PXC集群配置IPv6 【实操记录】MySQL主从配置 【实操记录】MySQL二进制安装包部署 MongoDB分片+副本集高可用集群的启停步骤
ORA-01658创建表或索引报错分析
likingzi · 2024-07-29 · via 博客园 - likingzi

一、报错信息

某项目最近在 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。这个只能在业务闲时操作,确保操作的表不要引起其他问题,比如先备份表。