今天发现数据库里报错,索引表空间空间不足,达到最大的32G的限制了,第一感觉就是索引不能更新,数据无法入库,可是看了点数据,似乎不太对,之前没有深入研究过此类现象,于是自己做了个测试来验证数据和索引是否是一个事务整体。以下模拟建立数据空间和索引空间,分配不同的大小进行验证。
SQL> create tablespace ts_data datafile '/app/ora_server/ora_base/oradata/gispub/ts_data.dbf' size 5M autoextend on next 50M MAXSIZE UNLIMITED;
Tablespace created
SQL> create tablespace ts_index datafile '/app/ora_server/ora_base/oradata/gispub/ts_index.dbf ' size 5M;
Tablespace created
SQL> CREATE table ts_table(
2 OWNER VARCHAR2(30),
3 OBJECT_NAME VARCHAR2(128) ,
4 SUBOBJECT_NAME VARCHAR2(30),
5 OBJECT_ID NUMBER,
6 DATA_OBJECT_ID NUMBER,
7 OBJECT_TYPE VARCHAR2(19),
8 CREATED DATE ,
9 LAST_DDL_TIME DATE ,
10 TIMESTAMP VARCHAR2(19),
11 STATUS VARCHAR2(7) ,
12 TEMPORARY VARCHAR2(1),
13 GENERATED VARCHAR2(1),
14 SECONDARY VARCHAR2(1))
15 tablespace ts_data;
Table created
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='TS_TABLE';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
TS_TABLE 0.0625
-- Create/Recreate indexes
SQL> create index idx_tt_owner_name on TS_TABLE (owner, object_name)
2 tablespace TS_INDEX;
Index created
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='IDX_TT_OWNER_NAME';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
IDX_TT_OWNER_NAME 0.0625
SQL> insert into ts_table select * from dba_objects;
49264 rows inserted
SQL> COMMIT;
Commit complete
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='TS_TABLE';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
TS_TABLE 6
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='IDX_TT_OWNER_NAME';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
IDX_TT_OWNER_NAME 4
第一次提交数据,数据和索引有足够的空间写入数据,查看段的大小情况如上。
SQL> insert into ts_table select * from dba_objects;
insert into ts_table select * from dba_objects
ORA-01654: unable to extend index SCOTT.IDX_TT_OWNER_NAME by 128 in tablespace TS_INDEX
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='IDX_TT_OWNER_NAME';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
IDX_TT_OWNER_NAME 4
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='TS_TABLE';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
TS_TABLE 8
此时再次插入数据,由于索引空间满了,无法继续扩展,此时抛出异常,这个时候索引的段依旧是4M,但是再次查询表的段大小的时候确发现段大小变大了,然而数据是否真的写入表中了呢?
SQL> select count(*) from ts_table;
COUNT(*)
----------
49264
这个数字说明了是第一次插入到数据库的数量,这样可以看出数据库的基本工作原理,首先先扩展表数据存储段,然后再扩展索引段,然后仔细看数据的变化为什么是从6变到8,我手动更改了下索引存储表空间的大小,看看可以的话索引段的扩展情况。
SQL> ALTER DATABASE DATAFILE '/app/ora_server/ora_base/oradata/gispub/ts_index.dbf ' RESIZE 8M;
Database altered
SQL> insert into ts_table select * from dba_objects;
49264 rows inserted
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='IDX_TT_OWNER_NAME';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
IDX_TT_OWNER_NAME 7
SQL> select segment_name,bytes/1024/1024 from dba_segments where owner='SCOTT' AND SEGMENT_NAME='TS_TABLE';
SEGMENT_NAME BYTES/1024/1024
-------------------------------------------------------------------------------- ---------------
TS_TABLE 11
至于数据段是如何分配的,这个稍后处理说明。
这个实验说明了数据库当索引和数据表空间中有一个无法插入的时候,数据或许索引是一个事务整体,无法单独插入数据或许更新索引。