暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据库中的跳号问题真的需要管理吗?

数据和云 2024-08-15
201
在数据库中,我们经常为对象或记录赋予一个顺序增长的序号作为标记,序列就是实现数据库功能的特性之一。有了顺序号就有了一类烦恼:如何防止跳号?
最近,在Oracle 23ai 版本中测试时,通过一个报错遭遇到Oracle为解决跳号问题引入和内部特性。
如下,在删除用户时遇到 ORA-01653 错误,不能扩展空间,引发空间扩展的对象是 OBJNUM_REUSE 。这是当删除对象时,数据库在 OBJNUM_REUSE 中增加记录,因空间不足而报错:
    SQL> drop user c##eygle cascade;
    drop user c##eygle cascade
    *
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-01653: unable to extend table SYS.OBJNUM_REUSE by 128 in tablespace SYSTEM
    此时数据库中共记录了15万个可以重用的对象号:
      SQL> select count(*) from OBJNUM_REUSE;


      COUNT(*)
      ----------
      154500
      问题原因很清楚,就是在删除用户时,触发了数据库的后台内部任务,级联引发空间扩展问题,从而出现了 ORA-01653 错误。
      但是 SYS.OBJNUM_REUSE 是一个什么对象呢?
      这是从Oracle 19c开始,增加的一个“对象号重用“的新特性,从而引入的数据库对象,objnum_reuse 是一个系统表,包含2个字段(记录了对象号和时间),还伴随创建了2个索引:
        create table objnum_reuse (
        obj# number not null,
        ins_date date)
        /
        create unique index i_objnum_reuse1 on objnum_reuse(obj#)
        /
        create index i_objnum_reuse2 on objnum_reuse(ins_date, obj#)
        /
        为什么要重用对象号呢?
        这是因为在Oracle RDBMS中有一些内部强加的限制,例如对象号在rowid中被引用(对象号占32bit),数据库中的对象号最多可以分配 4G 个。
        此限制会影响可以创建的对象数、可以对这些对象执行的DDL操作数以及可以创建的轻量级作业数。达到这个限制是灾难性的——数据库基本上变得不可用,因为无法创建新对象,无法在对象上运行DDL,也无法运行轻量级作业。如果数据库关闭,则可能无法重新打开。
        对于极其繁忙的数据库、经常反复创建对象的数据库,就可能用完对象号。
        在大约10年前,我遇到过一个案例,在SAP的系统中,由于大量的临时计算会频繁的创建和删除对象,导致对象号快速增长,在后续的DBMS_STATS任务调度上出现了问题。
        这是一个非常早期的数据库版本,叠加一些内部限制和序号保留,可用的用户对象号达不到理论数量。保留了当时的查询记录:
          SQL> select count(0) from dba_objects where object_id > power(2,31);


          COUNT(0)
          ----------
          1174755
          手工执行相关操作,都会遇到数值溢出的错误(还可能遇到ORA-600 [kkdlron-max-objid] 或 ORA-600 [15260]错误):
            SQL> BEGIN
            2 DBMS_AQADM.DROP_QUEUE_TABLE('Q_TABLE');
            3 END;
            4
            BEGIN
            *
            ERROR at line 1:
            ORA-01426: numeric overflow
            ORA-06512: at "SYS.DBMS_AQADM_SYS", line 4310
            ORA-06512: at "SYS.DBMS_AQADM", line 197
            ORA-06512: at line 2
            为了应对对象号浪费问题,现在Oracle 实现了自动的对象标识符回收方法,将丢弃对象的回收对象编号缓存在新的内部表中当系统对象标识符达到用尽状态时,数据库会无缝地切换到使用缓存的值。还提供了一个存储过程,用于手动收集废弃的对象号填充内部表。
            对象号重用,除了引入了以上描述的表和索引外,还包括:引入初始化隐含参数“_reuse_object_numbers”。
            当此参数设置为“0”时,对象标识符回收将关闭。若要激活回收功能,需要将其设置为“5”(不应设置为任何其他值)。此参数在19c中默认为“0”,但在23ai中,它默认为“5”。
            一旦激活,任何丢弃的对象(包括在安装和/或激活补丁之前创建的对象)的对象编号都将被回收。请注意,在这种情况下“已删除”意味着标识符已从SYS数据字典中删除,回收站中的项目并非如此(回收站中项目的编号需要Purge后才能回收)。
            针对这个特性,还引入了存储过程 OBJNUM_REUSE_HOLES。数据库中增加了一个名为OBJNUM_REUSE_HOLES的新过程。此程序可用于手动填充SYS.OBJNUM_REUSE表,其中包含通过扫描SYS获得的对象标识符。OBJ$表中未使用的标识符或序列中当前未使用的“孔”。
              PL/SQL过程已成功完成。
              SQL>exec objnum_reuse_holes(100000)
              注意,对于23ai之前的版本,必须显式激活特性。在数据库完全用完对象编号之前,可以随时设置“_reuse_object_numbers”参数。
              当该特性被激活时,对象标识符重用实际上不会生效,直到常规限制用完为止。但是,一旦设置了“_reuse_object_numbers”=5,就会开始捕获丢弃的对象编号。
              当达到对象标识符的最大限制并启用此特性时,系统将自动切换到从SYS表中获取对象标识符。OBJNUM_REUSE无缝连接,不会对应用程序造成任何中断或任何可见差异。
              Oracle的跳号治理,你觉得如何


              云和恩墨大讲堂 | 一个分享交流的地方 

              长按,识别二维码,加入万人交流社群


              请备注:云和恩墨大讲堂

                点个“在看” 
              你的喜欢会被看到❤

              文章转载自数据和云,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论