Different values reported for ALL_OBJECTS.OBJECT_ID and ALL_ARGUMENTS.OBJECT_ID in Oracle 21c

Viewed 217

I've noticed that for some objects in the SYS schema, the two following columns report different values:

For example:

select object_id
from all_objects
where object_name = 'DBMS_STATS'
and owner = 'SYS';

select distinct object_id
from all_procedures
where object_name = 'DBMS_STATS'
and owner = 'SYS';

select distinct object_id
from all_arguments
where package_name = 'DBMS_STATS'
and owner = 'SYS';

Produces

OBJECT_ID
---------
14813

OBJECT_ID
---------
14812

OBJECT_ID
---------
14812

This dbfiddle reproduces it:

  • On Oracle 21c
  • On Oracle 18c
  • But not on Oracle 11g

It seems that the data contained in ALL_OBJECTS is wrong? I can't find any entries in ALL_PROCEDURES for OBJECT_ID = 14813, and conversely, OBJECT_ID = 14812 produces this object in ALL_OBJECTS:

select owner, object_name, object_type
from all_objects
where object_id = 14812;

Results:

|OWNER |OBJECT_NAME       |OBJECT_TYPE|
|------|------------------|-----------|
|PUBLIC|XS$ROLE_GRANT_LIST|SYNONYM    |

Quite unrelated. Is this a known bug in the dictionary views? Or am I misunderstanding the semantics of the OBJECT_ID, which I believed was a unique object identifier across the dictionary?

I'm using Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production from here: https://hub.docker.com/r/gvenzl/oracle-xe, though a customer of ours can also reproduce it in 19c Enterprise Edition 19.5.0.0.0

3 Answers

Try it with and without the database being a pluggable database, eg

SQL> conn / as sysdba
Connected.
SQL> select object_id, object_type
  2  from all_objects
  3  where object_name = 'DBMS_STATS'
  4  and owner = 'SYS';

 OBJECT_ID OBJECT_TYPE
---------- -----------------------
     13795 PACKAGE
     19194 PACKAGE BODY

SQL>
SQL> select distinct object_id
  2  from all_procedures
  3  where object_name = 'DBMS_STATS'
  4  and owner = 'SYS';

 OBJECT_ID
----------
     13795

SQL> alter session set container = pdb1;

Session altered.

SQL> select object_id, object_type
  2  from all_objects
  3  where object_name = 'DBMS_STATS'
  4  and owner = 'SYS';

 OBJECT_ID OBJECT_TYPE
---------- -----------------------
     13796 PACKAGE
     19191 PACKAGE BODY

SQL>
SQL> select distinct object_id
  2  from all_procedures
  3  where object_name = 'DBMS_STATS'
  4  and owner = 'SYS';

 OBJECT_ID
----------
     13795
    127365

My hypothesis is that the ALL_ARGUMENTS et al are referring back to the "true" owning object, namely the one in the root container.

Plenty of weird little pointers and stuff going on here to support multi-tenant, eg

SQL> conn / as sysdba
Connected.
SQL> select dbms_metadata.get_ddl('VIEW','DBA_ARGUMENTS') from dual;

DBMS_METADATA.GET_DDL('VIEW','DBA_ARGUMENTS')
------------------------------------------------------------------------------------------------
---

  CREATE OR REPLACE FORCE NONEDITIONABLE VIEW "SYS"."DBA_ARGUMENTS" ("OWNER", "OBJECT_NAME", "PA
LOA
D", "SUBPROGRAM_ID", "ARGUMENT_NAME", "POSITION", "SEQUENCE", "DATA_LEVEL", "DATA_TYPE", "DEFAUL
_LE
NGTH", "IN_OUT", "DATA_LENGTH", "DATA_PRECISION", "DATA_SCALE", "RADIX", "CHARACTER_SET_NAME", "
_SU
BNAME", "TYPE_LINK", "TYPE_OBJECT_TYPE", "PLS_TYPE", "CHAR_LENGTH", "CHAR_USED", "ORIGIN_CON_ID"
  select
   OWNER, OBJECT_NAME, PACKAGE_NAME, OBJECT_ID, OVERLOAD,
   SUBPROGRAM_ID, ARGUMENT_NAME, POSITION, SEQUENCE,
   DATA_LEVEL, DATA_TYPE, DEFAULTED, DEFAULT_VALUE, DEFAULT_LENGTH,
   IN_OUT, DATA_LENGTH, DATA_PRECISION, DATA_SCALE, RADIX,
   CHARACTER_SET_NAME, TYPE_OWNER, TYPE_NAME, TYPE_SUBNAME,
   TYPE_LINK, TYPE_OBJECT_TYPE, PLS_TYPE, CHAR_LENGTH, CHAR_USED, ORIGIN_CON_ID
from INT$DBA_ARGUMENTS


SQL> alter session set container = pdb1;

Session altered.

SQL> select dbms_metadata.get_ddl('VIEW','DBA_ARGUMENTS') from dual;
ERROR:
ORA-31603: object "DBA_ARGUMENTS" of type VIEW not found in schema "SYS"
ORA-06512: at "SYS.DBMS_METADATA", line 6731
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105
ORA-06512: at "SYS.DBMS_METADATA", line 6718
ORA-06512: at "SYS.DBMS_METADATA", line 9734
ORA-06512: at line 1

SQL> select count(*)
  2  from dba_objects
  3  where object_name = 'DBA_ARGUMENTS'
  4  and object_type = 'VIEW';

  COUNT(*)
----------
         1

What you have found here appears to be a bug in the data dictionary and was reported as Bug 34293726 - Wrong object_id in ALL_OJBECTS leading to wrong results. Please don't get misled by the title of the bug itself, it is still to be determined whether or not the object_id in all_objects is wrong or in the other views.

The object_id reported in all_objects within the PDB is from a sub-object that is inherited by the CDB, while the other views report the object_id from the CDB itself.

In my database, the DBMS_STATS package has the object_id of 16334 in the CDB itself:

SQL> select object_id
from all_objects
where object_name = 'DBMS_STATS'
and owner = 'SYS';

 OBJECT_ID
----------
     16334
     22401

SQL> select distinct object_id
from all_procedures
where object_name = 'DBMS_STATS'
and owner = 'SYS';

 OBJECT_ID
----------
     16334

SQL> select distinct object_id
from all_arguments
where package_name = 'DBMS_STATS'
and owner = 'SYS';  2    3    4

 OBJECT_ID
----------
     16334

In the PDB, however, the object_id in all_objects is 16335:

SQL> alter session set container=cdb1_pdb1;

Session altered.

SQL> select object_id
from all_objects
where object_name = 'DBMS_STATS'
and owner = 'SYS';

 OBJECT_ID
----------
     16335
     22398

SQL> select distinct object_id
from all_procedures
where object_name = 'DBMS_STATS'
and owner = 'SYS';

 OBJECT_ID
----------
     16334

SQL> select distinct object_id
from all_arguments
where package_name = 'DBMS_STATS'
and owner = 'SYS';

 OBJECT_ID
----------
     16334

What's happening here becomes clearer when looking at cdb_objects in the CDB (which reports all objects within a CDB, or all objects within the PDB alone when executed in the PDB itself).

SQL> select con_id, owner, object_id, object_name, object_type
 from cdb_objects
 where object_name = 'DBMS_STATS';

CON_ID OWNER  OBJECT_ID OBJECT_NAME  OBJECT_TYPE
------ ------ --------- ------------ ---------------
     1 SYS        16334 DBMS_STATS   PACKAGE
     1 SYS        22401 DBMS_STATS   PACKAGE BODY
     1 PUBLIC     16335 DBMS_STATS   SYNONYM
     3 SYS        16335 DBMS_STATS   PACKAGE
     3 SYS        22398 DBMS_STATS   PACKAGE BODY
     3 PUBLIC     16336 DBMS_STATS   SYNONYM

Note how object_id 16335 in the PDB (con_id = 3) shows up as the package itself, while in the CDB (con_id = 1) the same object_id is reported as the public synonym. Meanwhile, the object_id 16334 refers to the actual object present in the CDB which is shared across PDBs.

The missing linkage is with the other ALL_* views inside the PDB, which are referring to the object in the CDB with object_id 16334 that happens to be an entirely different object in all_objects in the PDB:

SQL> select con_id,owner, object_id, object_name, object_type
 from cdb_objects
 where object_id = 16334;

CON_ID OWNER  OBJECT_ID OBJECT_NAME        OBJECT_TYPE
------ ------ --------- ------------------ -----------
     3 PUBLIC     16334 XS$ROLE_GRANT_LIST SYNONYM

Is this a known bug in the dictionary views? Or am I misunderstanding the semantics of the OBJECT_ID, which I believed was a unique object identifier across the dictionary?

You do understand the semantics of object_id correctly, this appears to be a bug and has been reported.

It may be also worthwhile to point out to other readers of this thread that one thing that has changed with the introduction of the CDB architecture is that there are multiple hierarchical dictionaries in play now. There can be up to three dictionaries: CDB --> (Application Root) --> PDB. The Application Root container is not mandatory, in the case above the hierarchy was simply CDB --> PDB.

In either case, the child inherits the objects present in the parent, i.e. objects in the CDB are available to all Application Root containers and objects available to the Application Root container (which includes objects from the CDB) are available to the PDB. And this is exactly what you see above in the inconsistency. Object 16334 is the object in the CDB, the actual DBMS_STATS package and object 16335 is the inherited package linkage in the PDB back to the CDB.

ALL_OBJECT has the OBJECT_ID from the pluggable database. ALL_ARGUMENTS reads the system metadata from CDB$ROOT though Extended Data Link and the OBJECT_ID comes from it:

---------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name              | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |                   |       |       |     1 (100)|          |       |       |
|*  1 |  FILTER                   |                   |       |       |            |          |       |       |
|   2 |   PARTITION LIST ALL      |                   |   200 | 44800 |     1 (100)| 00:00:01 |     1 |     2 |
|*  3 |    EXTENDED DATA LINK FULL| INT$DBA_ARGUMENTS |   200 | 44800 |     1 (100)| 00:00:01 |       |       |
|*  4 |   FIXED TABLE FULL        | X$KZSPR           |     2 |    18 |     0   (0)|          |       |       |
|   5 |   NESTED LOOPS SEMI       |                   |     1 |    18 |     2   (0)| 00:00:01 |       |       |
|*  6 |    FIXED TABLE FULL       | X$KZSRO           |     2 |    12 |     0   (0)|          |       |       |
|*  7 |    INDEX RANGE SCAN       | I_OBJAUTH1        |     1 |    12 |     1   (0)| 00:00:01 |       |       |
---------------------------------------------------------------------------------------------------------------
Related