你知道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