How to Use Oracle Data Pump When You Have Common Objects

One of the benefits of the multitenant architecture in Oracle Database is the concept of common objects. If you want to move data around with Oracle Data Pump, is there anything you must know?

What Are Common Objects

The documentation describes common objects as:

A common phenomenon defined in a root is the same in all containers plugged in to this root. … For example, if you create a common user account while connected to CDB$ROOT, then this user account is common to all PDBs and application roots in the CDB.

A simpler explanation:

The stuff you create as C##.... in the root container (CDB$ROOT).

The principles of commonality are:

  • A common phenomenon is the same in every existing and future container. …
  • Only a common user can alter the existence of common phenomena. More precisely, only a common user logged in to either the CDB root or an application root can create, destroy, or modify attributes of a user, role, or object that is common to the current container.

For illustration purposes, imagine a common profile used by a local user. You would create such as:

alter session set container=CDB$ROOT;
create profile c##commonprofile1 ... ;
alter session set container=pdb1;
create user localuser1 ... profile c##commonprofile1;

With other object types, you can make it even more complex, but the principles remain the same.

What Happens In Oracle Data Pump

On Export

Data Pump

  • Connects to the PDB.
  • Extracts the relevant data and metadata.

Using the above example, Data Pump extracts the user DDL. The user DDL specifies the use of a common profile.

On Import

Data Pump

  • Connects to the PDB.
  • Assumes that you have already created the common objects.
  • Creates the local user localuser1 and specifies the use of the common profile c##commonprofile1.

If the common profile does not exist already, the creation of the user fails:

Processing object type DATABASE_EXPORT/SCHEMA/USER
ORA-39083: Object type USER:"LOCALUSER1" failed to create with error:
ORA-02380: profile C##COMMONPROFILE1 does not exist

Failing sql is:
 CREATE USER "LOCAL1" ... PROFILE "C##COMMONPROFILE1"

Why Don’t Data Pump Create The Common Objects?

  • First, Data Pump connects to the PDB itself to perform the import. Since you must create common objects in the root container, that’s obviously a problem. The importing user might not have access to the root container, so switching containers and creating common objects is impossible.

  • Also, it would break the contract in the multitenant architecture that each PDB is isolated. If one PDB were allowed to create common objects, those objects would also be available in other PDBs, and the isolation would no longer exist.

  • Finally, it would open for all sorts of security issues if a user connected to a PDB could create common objects.

What Can You Do?

A CDB Blueprint

Ideally, you should have some CDB blueprint; A definition of the common objects used in your databases. When you create a new CDB, you have an afterburner that creates those common objects according to your company guidelines.

Examine the Dump File

You can also examine the DDLs in the Data Pump file and create a list of common objects.

  1. Extract the DDL:
    impdp ... sqlfile=import_ddls.sql
    
  2. Search for C## and build a list of common objects needed:
    grep -n -i "C##" import_ddls.sql
    
    This is a crude search, and I imagine awk aficionados can improve it.
  3. Extract the DDL for the common objects from the source CDB:
    l_stmt := dbms_metadata.get_ddl(...);
    dbms_output.put_line(l_stmt);
    l_stmt := dbms_metadata.get_granted_ddl(...);
    dbms_output.put_line(l_stmt);
    
    Use dbms_metadata.get_granted_ddl to extract object and role grants and system privileges.
  4. Create the common objects in the target CDB before import:
    alter session set container=cdb$root;
    create profile c##commonprofile1 ... ;
    

3 thoughts on “How to Use Oracle Data Pump When You Have Common Objects

  1. Hi Daniel,

    This post just came up during a search regarding common users and DDL, and is not immedeatly connected to my issue, but maybe, if you allow this comment here, also due to your reach, posting this here might help someone.

    I just had a revelation of the kind I like to avoid. We have a few systems with common users, that have quite complicated privilege setups. We now needed to copy these Users, including privileges, to another CDB.

    Not hard, I thought. Using DBMS_METADATA.GET_DDL and DBMS_METADATA.GET_GRANTED_DDL I can create a script for the users and all relevant grants and just execute that on the target. That works, with a massive BUT.

    The created grant-scripts do not contain the “CONTAINER” clause. For DBMS_METADATA.GET_DDL I could find a small footnote in the documentation for 26ai that the “CONTAINER” clause is not generated, unfortunately this also seems to apply to DBMS_METADATA.GET_GRANTED_DDL.

    So instead of

    GRANT CREATE MATERIALIZED VIEW TO “C##MYCOMMONUSER” CONTAINER=ALL;

    we would get

    GRANT CREATE MATERIALIZED VIEW TO “C##MYCOMMONUSER”;

    (modified example, applies to SYS PRIVS and ROLES) causing the users to miss quite a lot of necessary privileges inside the PDBs.

    You can imagine, that this “slight omission” caused many funny issues. ;)

    Like

    1. Hi Jan,

      I can see how this might come as a surprise, but judging from your example I tend to lean towards this is working as expected. Technically, this belongs with my colleagues in the multitenant team, so I can’t say for sure. If you need a definite answer you need to raise a SR with support. If needed, they can also support you if you want to raise an enhancement request.

      Regards,
      Daniel

      Like

      1. Yes, I also assume that this is “works as designed”. And now, knowing how it quitely suppresses the CONTAINER clause, I’ll work around this in the future. I’ll see if I want this enough to file an enhancement request.

        As I said, it’s not really directly related to your blog post, but since I stumbled across it while looking for my issue, I thougth, maybe someone else will, too. :)

        Like

Leave a comment