在Oracle数据库中对象号(Object ID)耗尽、可复用?
在oracle 数据库对象由 object_id 和 data_object_id 定义,后者的值也使用与 object_id 相同的内部唯一标识符。数据库中的对象标识符object id数量有硬性限制,一旦达到该限制,数据库将无法使用,必须重建。数据库中的唯一约束标识符数量也有硬性限制。触发上限时会提示ORA-600 [kkdlron-max-objid] or ORA-600 [15260]。
在 Oracle 数据字典中,某些标识符以内部序列保存。由于这些标识符在代码中的许多领域都使用,因此它们保存在使用上限为 4,294,967,293 的数据类型的变量中。像object,user和constraint 都样的限制,无法复用(即使是删除)。关注sys基表con$、obj$或user$ 都有一个_NEXT_xx值,它是向前的下标值,也是一个单调递增的序列。
达到此限制是灾难性的,Mechanism to Recycle Database Object Identifiers (Doc ID 2923706.1)描述如下
由于使用的内部数据类型,Oracle RDBMS 具有一些内部强加的限制。其中一个限制涉及在数据库生命周期内可以创建的对象标识符的数量。此限制会影响可创建的对象数量、可针对这些对象执行的 DDL 操作数量以及可创建的轻量级作业数量。达到此限制是灾难性的 – 数据库基本上变得不可用,因为无法创建新对象,无法在对象上运行 DDL,也无法运行轻量级作业。如果数据库关闭,可能无法重新打开它。
Bug 28632799 的修复在所用约束数或对象数达到 99% 时使数据库崩溃或中止相关 PDB.
Oracle 数据库中可以创建的对象数量的限制,不用担心,这个限制非常高4,294,967,294, 但是,这些值中的 4000 万个被保留在高端用于其他目的,因此该值的实际最大值是 4,254,950,911。略高于 42 亿。不过前几年确实听说过有的客户有不良的编程习惯,在存储过程中大量的循环,”临时”表, 反复的创建、删除,最终导致数据库对象耗尽,为了防止达到这个限制,在 Oracle Database 19c 和 23ai 中引入了一种重用对象 ID的机制。同时引入了三个变化:
1,隐藏参数_reuse_object_numbers
控制重复使用数据库中的对象编号并获得更多的空间。它自 Oracle 19.19.0 Release Update (RU) 开始引入,
SQL> @pd reuse_obj Show all parameters and session values from x$ksppi/x$ksppcv... NUM N_HEX NAME VALUE DESCRIPTION ---------- ----- -------------------------------------------------------- ------------------------------ --------------------------------------------------------------------------------------------------- 3930 F5A _reuse_object_numbers 5 reuse object numbers 3931 F5B _reuse_object_number_delay 0 delay in days before reusing object numbers 3932 F5C _reuse_object_numbers_qa 0 reuse object numbers testing
2,表SYS.OBJNUM_REUSE
为了支持此功能,Oracle 19.19 还引入了一个新表和一个新过程。这是缓存回收的对象标识符以供以后使用的表。请注意,这是一个数据字典表,如果 SYS.OBJNUM_REUSE 中的行数达到零,则在再次运行 OBJNUM_REUSE_HOLES 之前,将无法创建任何新对象/执行 DDL/运行轻量级作业。
select OBJ#, INS_DATE from OBJNUM_REUSE order by 1;
该表缓存了要重复使用的对象编号。但是当您第一次查询它时,它是空的。因此,当您的数据库不太活跃时,需要使用此过程OBJNUM_REUSE_HOLES首次调用填充,23ai 中不需要过程OBJNUM_REUSE_HOLES , 有其自动维护。
更多请查看MOS说明:2923706.1 – 回收数据库对象标识符的机制
3,存储过程 OBJNUM_REUSE_HOLES
OBJNUM_REUSE_HOLES要在停机时间运行,如果未出现OBJECT_ID紧张前,不建议手动去运行这个存储过程。
该过程必须仅在数据库处于受限模式且系统上没有任何活动时运行。关闭服务和监听器以确保数据库被隔离会更安全。
PROCEDURE objnum_reuse_holes Argument Name Type In/Out Default? ------------------------------ ----------------------- ------- -------- MAXCOUNT NUMBER IN DEFAULT
如果调用时没有输入参数,它将扫描整个 SYS.OBJj$ 表,可能会消耗大量的时间,如下调用此过程来回收100000个值大约需要10-20分钟,此过程只能手动调用。安装补丁不会运行它.
exec objnum_reuse_holes(100000);
如何启用它?
在 Oracle Database 19c(从 19.19.0 开始)中, 引入了一个新的下划线参数:_reuse_object_numbers, 19c 中的默认值为0(零),该功能仍然默认关闭。要启用它,请将其设置为5。这也已经是 Oracle Database 23ai 中的默认值。
alter system set "_reuse_object_numbers"= 5 ;
无需重新启动。
一旦激活此功能,任何被丢弃的对象的对象编号都会被回收。“丢弃”具体是指标识符已从 OBJ$ 中删除。如果您已打开回收站,则不会回收被丢弃的对象,因为它们仍存在于数据库中(只是名称不同,通常以 BIN$ 开头)。手动purge清空或使用以下命令将其关闭:
alter system set recyclebin='OFF' scope=spfile;
不幸的是,您需要重新启动数据库才能使其生效。
监控object id使用
可以按如下方式监视object id 序列中剩余的对象标识符数量:
select dataobj# from sys.obj$ where name='_NEXT_OBJECT';
-- enjoy --
References:
Internal Database Limits on Number of Objects, Constraints, and Users (Doc ID 2660231.1)
https://mikedietrichde.com/2024/07/04/reuse-object-ids-in-oracle-database-19c-and-23ai/
Mechanism to Recycle Database Object Identifiers (Doc ID 2923706.1)
对不起,这篇文章暂时关闭评论。