你知道Oracle object_id最大是多少吗?
我们知道Oracle数据库中创建一个新的对象无论是表、还是index都会创建一个全局唯一标识object_id(其实还有个data_object_id)。同时我们也知道本质上去是读取obj$._next_object来实现的。
那么Oracle数据库中究竟能创建多少个对象呢?实际上以前我们确实遇到过一些客户的环境,频繁的创建和drop 对象,最后达到了object_id最大值,最终导致数据库无法正常使用,只能重建库。
首先我们来看下官方文档的一些说明:
从文档说明来看,在12c版本中最大支持大约是42亿个对象,按理说这个值已经很大很大了,毕竟我见过最为庞大的Oracle系统,是其中包含300多万个对象。别说300万了,之前我们一个客户100多万对象,使用xtts做跨平台迁移,其中元数据导出导入接近20个小时,非常夸张。
在23c之前的版本中,对于Oracle object_id来讲,实际上是无法重用的。如果你遇到一些垃圾应用,频繁drop、create操作的数据库系统,那么很可能就会遇到类似问题。这里我贴一下几年前我的处理方式:
SQL> SELECT dataobj# FROM SYS.obj$ WHERE NAME = '_NEXT_OBJECT';
<br>
DATAOBJ#
----------
87370
<br>
SQL> drop table t1;
<br>
Table dropped.
<br>
SQL> c/t1/t2
1* drop table t2
SQL>
<br>
Table dropped.
<br>
SQL> c/t2/t3
1* drop table t3
SQL>
<br>
Table dropped.
<br>
SQL> c/t3/t4
1* drop table t4
SQL>
<br>
Table dropped.
<br>
SQL> c/t4/t5
1* drop table t5
SQL>
<br>
Table dropped.
<br>
SQL> conn as sysdba
Connected.
SQL> purge dba_recyclebin;
<br>
DBA Recyclebin purged.
<br>
SQL> select obj#,dataobj# ,name FROM SYS.obj$ WHERE dataobj# > 87364 order by 2;
<br>
OBJ# DATAOBJ# NAME
---------- ---------- ------------------------------
1 87375 _NEXT_OBJECT
<br>
SQL> update SYS.obj$ set DATAOBJ#=87365 where NAME='_NEXT_OBJECT';
<br>
1 row updated.
<br>
SQL> commit;
<br>
Commit complete.
<br>
SQL> conn roger/roger
Connected.
SQL> create table t1 as select * from sys.dba_objects where rownum < 100;
<br>
Table created.
<br>
SQL> c/t1/t2
1* create table t2 as select * from sys.dba_objects where rownum < 100
SQL>
<br>
Table created.
<br>
SQL> c/t2/t3
1* create table t3 as select * from sys.dba_objects where rownum < 100
SQL>
<br>
Table created.
<br>
SQL> select obj#,dataobj# ,name FROM SYS.obj$ WHERE dataobj# > 87364 order by 2;
<br>
OBJ# DATAOBJ# NAME
---------- ---------- ------------------------------
87373 87373 T1
87374 87374 T2
87375 87375 T3
1 87380 _NEXT_OBJECT
<br>
SQL>
SQL> SELECT CASE
2 WHEN (nextobjnum - maxobjnum) > 0
3 THEN 'GOOD'
ELSE 'BAD'
4 5 END "OBJ_NUM_STATE"
6 FROM (SELECT (SELECT dataobj#
7 FROM SYS.obj$
8 WHERE NAME = '_NEXT_OBJECT') nextobjnum,
9 (SELECT MAX (obj#)
10 FROM SYS.obj$) maxobjnum
11 FROM DUAL);
<br>
OBJ_NUM_STAT
------------
GOOD