CDB & PDB LISTENER Files Configuration.


Here are the contents of my listener.ora file:

[oracle@CDB admin]$ cat listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/12.1.0/dbhome_1/network/admin/listener.ora
# Generated by Oracle configuration tools.
#VALID_NODE_CHECKING_REGISTRATION_LISTENER=ON
#SSL_VERSION = 1.0
#USE_SID_AS_SERVICE_listener=on

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = CDB.oraclecloud)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = CDB)
      (SID_NAME = CDB)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = PDB1)
      (SID_NAME = PDB1)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = PDB2)
      (SID_NAME = PDB2)
  )
 )

Following are the contents of my tnsnames.ora file:

[oracle@CDB admin]$ cat tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/12.1.0/dbhome_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

CDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = CDB.oraclecloud)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = CDB)
    )
  )
PDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = CDB.oraclecloud)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = PDB1)
    )
  )
PDB2 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = CDB.oraclecloud)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = PDB2)
    )
  )





Unplug a Pluggable Database (PDB)

Unplug a Pluggable Database (PDB) Manually

Before attempting to unplug a PDB, you must make sure it is closed.

To unplug the database use the ALTER PLUGGABLE DATABASE command with the UNPLUG INTO clause to specify the location of the XML metadata file.

SQL>ALTER PLUGGABLE DATABASE pdb2 CLOSE;

SQL>ALTER PLUGGABLE DATABASE pdb2 UNPLUG INTO '/u01/app/oracle/oradata/cdb1/pdb2/pdb2.xml';

The pluggable database is still present, but you shouldn't open it until the metadata file
 and all the datafiles are copied somewhere safe.

SQL>SELECT name, open_mode
FROM   v$pdbs
ORDER BY name;

NAME       OPEN_MODE
------------------------------ ----------
PDB$SEED       READ ONLY
PDB1       MOUNTED
PDB2       MOUNTED
PDB3       READ WRITE


You can delete the PDB, choosing to keep the files on the file system.

SQL> DROP PLUGGABLE DATABASE pdb2 KEEP DATAFILES;

SELECT name, open_mode
FROM   v$pdbs
ORDER BY name;

NAME       OPEN_MODE
------------------------------ ----------
PDB$SEED       READ ONLY
PDB1       MOUNTED
PDB3       READ WRITE

Plugin a Pluggable Database (PDB)

Plugin a Pluggable Database (PDB) Manually

There is an update to this functionality in Oracle 12.2, described here.

Plugging in a PDB into the CDB is similar to creating a new PDB. First check the PBD is compatible with the CDB by calling the DBMS_PDB.CHECK_PLUG_COMPATIBILITY function, passing in the XML metadata file and the name of the PDB you want to create using it.

SQL> SET SERVEROUTPUT ON
DECLARE
  l_result BOOLEAN;
BEGIN
  l_result := DBMS_PDB.check_plug_compatibility(
                pdb_descr_file => '/u01/app/oracle/oradata/cdb1/pdb2/pdb2.xml',
                pdb_name       => 'pdb2');

  IF l_result THEN
    DBMS_OUTPUT.PUT_LINE('compatible');
  ELSE
    DBMS_OUTPUT.PUT_LINE('incompatible');
  END IF;
END;
/
compatible

PL/SQL procedure successfully completed.



If the PDB is not compatible, violations are listed in the PDB_PLUG_IN_VIOLATIONS view. If the PDB is compatible,

 create a new PDB using it as the source. If we were creating it with a new name we might do something like this.

SQL> CREATE PLUGGABLE DATABASE pdb5 USING '/u01/app/oracle/oradata/cdb1/pdb2/pdb2.xml'
  FILE_NAME_CONVERT=('/u01/app/oracle/oradata/cdb1/pdb2/','/u01/app/oracle/oradata/cdb1/pdb5/');
Instead, we want to plug the database back into the same container, so we don't need to copy the files or
recreate the temp file, so we can do the following.

SQL>  CREATE PLUGGABLE DATABASE pdb2 USING '/u01/app/oracle/oradata/cdb1/pdb2/pdb2.xml'
  NOCOPY
  TEMPFILE REUSE;

SQL>  ALTER PLUGGABLE DATABASE pdb2 OPEN READ WRITE;

SQL> SELECT name, open_mode
FROM   v$pdbs
ORDER BY name;

NAME       OPEN_MODE
------------------------------ ----------
PDB$SEED       READ ONLY
PDB1       MOUNTED
PDB2       READ WRITE
PDB3       READ WRITE

Cloning Pluggable Databases (PDB).

Clone a Pluggable Database (PDB) Manually

Cloning an existing local PDB is like creating a new PDB from the seed PDB,

except now we are using non-seed PDB as the source, which we must identify using the FROM clause.

 Make sure the source PDB is open in READ ONLY mode.

Setting the source to read-only is not necessary for Oracle 12cR2.

SQL> ALTER PLUGGABLE DATABASE pdb3 CLOSE;
SQL> ALTER PLUGGABLE DATABASE pdb3 OPEN READ ONLY;

SQL> CREATE PLUGGABLE DATABASE pdb4 FROM pdb3
  FILE_NAME_CONVERT=('/u01/app/oracle/oradata/cdb1/pdb3/','/u01/app/oracle/oradata/cdb1/pdb4/');

SQL> ALTER PLUGGABLE DATABASE pdb4 OPEN READ WRITE;


Switch the source PDB back to read/write if you made it read-only.

SQL> ALTER PLUGGABLE DATABASE pdb3 CLOSE;
SQL> ALTER PLUGGABLE DATABASE pdb3 OPEN READ WRITE;

The cloning syntax also allows for cloning from remote databases using a database link in the local CBD.


There are a few restrictions associated with this functionality.

How to create pdb in oracle 12c.

How to create a pluggable database PDB in a multitenant container database CDB using the files of the seed PDB$SEED

The new architecture provided by Oracle Database 12c enables an Oracle database to function as a
multitenant container database (CDB):
it can include zero, one, or many pluggable databases (PDBs), that is a portable collection of schemas, schema objects and nonschema objects.

A multitenant container database (CDB) is formed by the following components:
- the root container (and exactly one root) named CDB$ROOT that stores Oracle-supplied metadata and common users
 (a database user known in every container);
- the seed template (and exactly one seed) named PDB$SEED used, if you want, to create new PDBs.
It's not possible to add objects to or modify objects in the seed: it works only in READ ONLY mode;
- pluggable databases (zero, one, or many PDBs) named as you prefer that are your "old idea of databases"
 before Oracle Database 12c. A pluggable database contains the data and code required by your software
application and is fully backward compatible with Oracle Database releases before Oracle Database 12c.

The options for creating a pluggable database (the so called PDB) fall into two main categories:
copying and plugging in as you will see in this post and in the next posts.

Talking about copying, you have two options to copy a pluggable database:
create a pluggable database (PDB) in a multitenant container database (CDB) using the files of the seed (PDB$SEED);
create it by cloning a source PDB and plugging the clone into the CDB (bear in mind that the source PDB can be in the local CDB or in a remote CDB).

Today I'm going to describe how to copy a pluggable database using the files of the seed from the SQL*Plus command line.

If you want to see how to create a pluggable database copying the files of the seed using DBCA you can simply watch the following video (I will create a post about it using screenshot as soon as possible).

To create a new pluggable database copying the files of the seed you have to ensure that the current container is the root: 

SQL> SELECT SYS_CONTEXT ('USERENV', 'CON_NAME') FROM DUAL;

SYS_CONTEXT('USERENV','CON_NAME')
--------------------------------------------------------------------------------
CDB$ROOT

your multitenant container database CDB must be also in read/write mode. My CDB is called CDB001:

SQL> select NAME, CDB, CON_ID, OPEN_MODE from V$DATABASE;

NAME   CDB   CON_ID OPEN_MODE
--------- --- ---------- --------------------
CDB001   YES        0 READ WRITE

Your script must include the CREATE PLUGGABLE DATABASE statement and eventually some other clauses, such as the following I used in my script:

- STORAGE: specify the limit of the amount of storage the PDB can use. Omitting this clause is equivalent to specify an unlimited amount;

- DEFAULT TABLESPACE: specify a default permanent tablespace for non-SYSTEM users. When you omit this clause the SYSTEM tablespace will be used as default permanent tablespace for non-SYSTEM users and this is not recommended;

- FILE_NAME_CONVERT: specify the target locations of the data files whereas the source files are those associated with the seed.

This parameter is required when Oracle Managed Files is not enabled and the PDB_FILE_NAME_CONVERT initialization parameter is not set

- other clauses you can use are: ROLES, TEMPFILE REUSE and PATH_PREFIX.

SQL> CREATE PLUGGABLE DATABASE PDB002
  2  ADMIN USER PDB002_ADMIN IDENTIFIED BY oracle
  3  storage (maxsize 5G MAX_SHARED_TEMP_SIZE 500M)
  4  DEFAULT TABLESPACE "USERS" DATAFILE '/app/oracle/oradata/CDB001/PDB002/PDB002_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON
  5  file_name_convert=('/app/oracle/oradata/CDB001/pdbseed/system01.dbf','/app/oracle/oradata/CDB001/PDB002/system01.dbf','/app/oracle/oradata/CDB001/pdbseed/sysaux01.dbf','/app/oracle/oradata/CDB001/PDB002/sysaux01.dbf','/app/oracle/oradata/CDB001/pdbseed/temp01.dbf','/app/oracle/oradata/CDB001/PDB002/temp01.dbf');

Pluggable database created.
From the alert log (vi /app/oracle/diag/rdbms/cdb001/CDB001/trace/alert_CDB001.log):
Sat Jul 20 16:21:48 2013
CREATE PLUGGABLE DATABASE PDB002 ADMIN USER PDB002_ADMIN IDENTIFIED BY * storage (maxsize 5G MAX_SHARED_TEMP_SIZE 500M) DEFAULT TABLESPACE "USERS" DATAFILE '/app/oracle/oradata/CDB001/PDB002/PDB002_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON file_name_convert=('/app/oracle/oradata/CDB001/pdbseed/system01.dbf','/app/oracle/oradata/CDB001/PDB002/system01.dbf','/app/oracle/oradata/CDB001/pdbseed/sysaux01.dbf','/app/oracle/oradata/CDB001/PDB002/sysaux01.dbf','/app/oracle/oradata/CDB001/pdbseed/temp01.dbf','/app/oracle/oradata/CDB001/PDB002/temp01.dbf')
Sat Jul 20 16:22:35 2013
****************************************************************
Pluggable Database PDB002 with pdb id - 4 is created as UNUSABLE.
If any errors are encountered before the pdb is marked as NEW,
then the pdb must be dropped
****************************************************************
Deleting old file#2 from file$
Deleting old file#4 from file$
Adding new file#10 to file$(old file#2)
Adding new file#11 to file$(old file#4)
Successfully created internal service pdb002 at open
CREATE TABLESPACE USERS DATAFILE  '/app/oracle/oradata/CDB001/PDB002/PDB002_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON  SEGMENT SPACE MANAGEMENT AUTO
Completed: CREATE TABLESPACE USERS DATAFILE  '/app/oracle/oradata/CDB001/PDB002/PDB002_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON  SEGMENT SPACE MANAGEMENT AUTO
Sat Jul 20 16:22:49 2013
ALTER SYSTEM: Flushing buffer cache inst=0 container=4 local
****************************************************************
Post plug operations are now complete.
Pluggable database PDB002 with pdb id - 4 is now marked as NEW.
****************************************************************
Completed: CREATE PLUGGABLE DATABASE PDB002 ADMIN USER PDB002_ADMIN IDENTIFIED BY * storage (maxsize 5G MAX_SHARED_TEMP_SIZE 500M) DEFAULT TABLESPACE "USERS" DATAFILE '/app/oracle/oradata/CDB001/PDB002/PDB002_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON file_name_convert=('/app/oracle/oradata/CDB001/pdbseed/system01.dbf','/app/oracle/oradata/CDB001/PDB002/system01.dbf','/app/oracle/oradata/CDB001/pdbseed/sysaux01.dbf','/app/oracle/oradata/CDB001/PDB002/sysaux01.dbf','/app/oracle/oradata/CDB001/pdbseed/temp01.dbf','/app/oracle/oradata/CDB001/PDB002/temp01.dbf')

As you can see when you create a pluggable database from the SQL*Plus command line it is open in MOUNTED mode.
This is a different behaviour compared with the same operation performed by DBCA: in the final step DBCA is able to open the new pluggable database in READ WRITE mode.

SQL> select NAME, OPEN_MODE, CON_ID from V$PDBS;

NAME          OPEN_MODE      CON_ID
------------------------------ ---------- ----------
PDB$SEED         READ ONLY    2
PDB001          READ WRITE    3
PDB002          MOUNTED     4

To open your new pluggable database in READ WRITE mode execute the following alter pluggable database command:

SQL> alter pluggable database pdb002 open read write;

Pluggable database altered.

Now query again the V$PDBS view: your pluggable database is now available to the application.

SQL> select NAME, OPEN_MODE, CON_ID from V$PDBS;

NAME          OPEN_MODE      CON_ID
------------------------------ ---------- ----------
PDB$SEED         READ ONLY    2
PDB001          READ WRITE    3
PDB002          READ WRITE    4

Create Pluggable Database Manually using SQL Prompt

we will have a look & hands-on on creating a PDB manually with the help of SQL Prompt.

We can create PDB using PDB_FILE_NAME_CONVERT initialization parameter,
In following example i am going to create new Pluggable Database, name: ‘newpdb’

[oracle@OL6 ~]$ sqlplus “/ as sysdba”
// Ensure database globale name by following SQL query:

SQL> select global_name from global_name;

GLOBAL_NAME
——————————————————————————–
ORCL

// Create new pluggable database by following set of SQL queries:
SQL> ALTER SESSION SET PDB_FILE_NAME_CONVERT=’/u01/app/oracle/oradata/pdbseed/’,’/u01/app/oracle/oradata/newpdb/’;

Session altered.

SQL> CREATE PLUGGABLE DATABASE newpdb ADMIN USER pdbadmin IDENTIFIED BY Admin123;

Pluggable database created.


// Pluggable database has been created successfully, ensure changes by issuing the following query:
column pdb_name FORMAT A25;
SQL> select name,open_mode from v$pdbs;

NAME OPEN_MODE
—————————— ———-
PDB$SEED READ ONLY
NEWPDB MOUNTED

OR

column pdb_name FORMAT A25;

SQL>SELECT pdb_name, status FROM dba_pdbs ORDER BY pdb_name;

PDB_NAME STATUS
————————- ————-
NEWPDB NEW
PDB$SEED NORMAL

// Above result shows that, newly created pluggable database is in mount state,
Pluggable databases automatically created in mount state, Issue the following query to open pluggable database:

SQL> alter pluggable database newpdb open;

Pluggable database altered.


// Ensure the changes by following SQL query, Now newly created pluggable database is in READ WRITE (open) state.

SQL> select name,open_mode from v$pdbs;

NAME OPEN_MODE
—————————— ———-
PDB$SEED READ ONLY
NEWPDB READ WRITE

Connect your pluggable database with following:

SQL> show con_name

CON_NAME
——————————
CDB$ROOT

SQL> alter session set container=newpdb;

Session altered.

SQL> show con_name

CON_NAME
——————————
NEWPDB

You are now connected to your newly created PDB. 

Connecting to Container Databases (CDB) and Pluggable Databases (PDB) in Oracle Database 12c


What are the Oracle 12c Pluggable databases?  How does a pluggable database work?

Answer:  A pluggable database is a new construct whereby you can encapsulate a sub-set of Oracle data tables and indexes along with its associated metadata from the data dui dictionary.  You start by creating a "root" instance database, called a container database (CDB).  This container is used to hold many pluggable database "tenants" (PDB's), in a type of architectural separation.
The most important part of this separation is the "split" data dictionary, whereby everything needed for a PDB is self-contained in this sub-set of the metadata.






 Unlike a traditional database where only one database can exist per instance, the Oracle 12c pluggable databases allow multiple databases within an instance.  Oracle pluggable databases ease the movement into database consolidation because the data dictionary information (obj$, tab$ and source$) are independent of any container database.  All PDB's within the container share a common LGWR process.
This container can then be populated with sub-sets of a schema and then be can be un-plugged from one instance and re-added to another instance quickly.  Because the table definitions, index definitions, constraints and data all reside within the PDB, they can be easily copied and moved between instances and servers.   Oracle has termed "multi-tenancy" to describe the process of creating a CDB that contains many "tenant" PDB's.
The pluggable databases provide significant reduction in overhead on systems (like Exadata) where we'd like to host multiple databases, but can't consolidate them due to conflicts that prevent them running under the same instance (public synonyms / database links, schema name collision, etc). There are several benefits to pluggable databases:

1 - Easy fast cloning:  Simply copy the PDB very quickly

2 - Easy upgrades:  Just copy/move the PDB to a container running a higher release of Oracle
There is a new pluggable database administrator role in 12c called the CDB Administrator role.


Connecting to the root of a container database is the same as that of any previous database instance. On the database server you can use OS Authentication.

[oracle@vmdb12c ~]$ sqlplus / as sysdba

SQL> show con_name

CON_NAME
——————————
CDB$ROOT

The V$SERVICES views can be used to display available services from the database.

SQL> select name,pdb from v$services order by 2;

NAME                 PDB
——————– ———-
zwcXDB               CDB$ROOT
SYS$BACKGROUND       CDB$ROOT
SYS$USERS            CDB$ROOT
zwc                  CDB$ROOT
zhongwc1             ZHONGWC1
zhongwc2             ZHONGWC2

6 rows selected.

The lsnrctl utility allows you to display the available services from the command line.

[oracle@vmdb12c ~]$ lsnrctl status

LSNRCTL for Linux: Version 12.1.0.1.0 – Production on 06-SEP-2013 22:10:41

Copyright (c) 1991, 2013, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=vmdb12c)(PORT=1521)))
STATUS of the LISTENER
————————
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 12.1.0.1.0 – Production
Start Date                06-SEP-2013 19:32:46
Uptime                    0 days 2 hr. 37 min. 54 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/oracle/product/12.1.0/dbhome_1/network/admin/listener.ora
Listener Log File         /u01/app/oracle/diag/tnslsnr/vmdb12c/listener/alert/log.xml
Listening Endpoints Summary…
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=vmdb12c)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
Services Summary…
Service "zhongwc1" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
Service "zhongwc2" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
Service "zwc" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
Service "zwcXDB" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
The command completed successfully

[oracle@vmdb12c ~]$ lsnrctl service  

LSNRCTL for Linux: Version 12.1.0.1.0 – Production on 06-SEP-2013 22:10:45

Copyright (c) 1991, 2013, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=vmdb12c)(PORT=1521)))
Services Summary…
Service "zhongwc1" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
    Handler(s):
      "DEDICATED" established:5 refused:0 state:ready
         LOCAL SERVER
Service "zhongwc2" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
    Handler(s):
      "DEDICATED" established:5 refused:0 state:ready
         LOCAL SERVER
Service "zwc" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
    Handler(s):
      "DEDICATED" established:5 refused:0 state:ready
         LOCAL SERVER
Service "zwcXDB" has 1 instance(s).
  Instance "zwc", status READY, has 1 handler(s) for this service…
    Handler(s):
      "D000" established:0 refused:0 current:0 max:1022 state:ready
         DISPATCHER <machine: vmdb12c, pid: 4294>
         (ADDRESS=(PROTOCOL=tcp)(HOST=vmdb12c)(PORT=34716))
The command completed successfully

Connections using services are unchanged from previous versions.

[oracle@vmdb12c ~]$ sqlplus system/oracle@192.168.1.14:1521/zhongwc1

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         3 ZHONGWC1                       READ WRITE NO

SQL> show con_name

CON_NAME
——————————
ZHONGWC1

[oracle@vmdb12c ~]$ sqlplus system/oracle@192.162.200.10:1521/zhongwc2

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         4 ZHONGWC2                       READ WRITE NO

SQL> show con_name

CON_NAME
——————————
ZHONGWC2

[oracle@vmdb12c ~]$ sqlplus system/oracle@zhongwc1

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         3 ZHONGWC1                       READ WRITE NO

SQL> show con_name

CON_NAME
——————————
ZHONGWC1

[oracle@vmdb12c ~]$ sqlplus system/oracle@zhongwc2

SQL> show con_name

CON_NAME
——————————
ZHONGWC2

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         4 ZHONGWC2                       READ WRITE NO

tnsnames.ora
ZWC =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = vmdb12c)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = zwc)
    )
  )


zhongwc1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = vmdb12c)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = zhongwc1)
    )
  )


zhongwc2 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = vmdb12c)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = zhongwc2)
    )
  )

LISTENER_ZWC =
  (ADDRESS = (PROTOCOL = TCP)(HOST = vmdb12c)(PORT = 1521))



When logged in to the CDB as an appropriately privileged user, the ALTER SESSION command can be used to switch between containers within the container database.

[oracle@vmdb12c ~]$ sqlplus / as sysdba

SQL> alter session set container=zhongwc1;

Session altered.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         3 ZHONGWC1                       READ WRITE NO

SQL> alter session set container=zhongwc2;

Session altered.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         4 ZHONGWC2                       READ WRITE NO

SQL> alter session set container=cdb$root;

Session altered.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
———- —————————— ———- ———-
         2 PDB$SEED                       READ ONLY  NO
         3 ZHONGWC1                       READ WRITE NO
         4 ZHONGWC2                       READ WRITE NO

SQL> select sys_context('USERENV','CON_NAME') from dual;

SYS_CONTEXT('USERENV','CON_NAME')
——————————————————————————–
CDB$ROOT

SQL> alter session set container=zhongwc1;

Session altered.

SQL> select sys_context('USERENV','CON_NAME') from dual;

SYS_CONTEXT('USERENV','CON_NAME')
——————————————————————————–
ZHONGWC1

SQL> alter session set container=zhongwc2;

Session altered.

SQL> select sys_context('USERENV','CON_NAME') from dual;

SYS_CONTEXT('USERENV','CON_NAME')
——————————————————————————–
ZHONGWC2

Connect to the container database as usual and use the V$INSTANCE view to see where I’m at.

[oracle@oel6 dbhome_1]$ sqlplus / as sysdba

SQL> select instance_name, version, status, con_id from v$instance;
INSTANCE_NAME     VERSION           STATUS       CON_ID
----------------- ----------------- ------------ ----------
ora12cb                  12.1.0.1.0         OPEN          0

Lets move into a PDB.  I have quite a few PDBs created, lets just use PDB1.

SQL> alter session set container=PDB1;
Session altered.

Did I actually move containers?  How can I tell?  Instead of selecting INSTANCE_NAME from V$INSTANCE; we have two new SHOW commands that will provide us the information we are looking for.  These command are quite simple (SHOW CON_ID & SHOW CON_NAME).

SQL> show con_id
CON_ID
------------------------------
3
SQL> show con_name
CON_NAME
------------------------------
PDB1

Now that we are confident that we are in PDB1, lets take a look at the V$INSTANCE view again.  What you will notice is that V$INSTANCE provides us with information relative to the container database (CDB).  It only makes sense that the V$INSTANCE would return CDB information. So, how do we identify items related to the pluggable database (PDB) without the SHOW commands?

Lets take a look at a view that is similar to V$INSTANCE.  Enter the V$PDBS view!

SQL> desc v$pdbs;
 Name                    Null?    Type
 ----------------------- -------- ----------------------------
 CON_ID                           NUMBER
 DBID                             NUMBER
 CON_UID                          NUMBER
 GUID                             RAW(16)
 NAME                             VARCHAR2(30)
 OPEN_MODE                        VARCHAR2(10)
 RESTRICTED                       VARCHAR2(3)
 OPEN_TIME                        TIMESTAMP(3)
 CREATE_SCN                       NUMBER
 TOTAL_SIZE                       NUMBER

This view provides similar information as V$INSTANCE does; yet is only specific to PDBs.  If we wanted to find out the container_id, name, open_mode and size of the PDB we are currently connected to, we can use this query:

SQL> select con_id, name, open_mode, total_size from v$pdbs;

CON_ID     NAME                           OPEN_MODE  TOTAL_SIZE
---------- ------------------------------ ---------- ----------
 3         PDB1                           READ WRITE 393216000

What is interesting to point out, is that since we used an ALTER SESSION statement to switch to PDB1, the V$PDBS view only lists the PDB we are currently working in.  If we want to get a complete list of PDBs within the container database, we need to go back to the root container database and run the same SQL statement.

SQL> alter session set container=CDB$ROOT;
Session altered.

SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT

SQL> select con_id, name, open_mode, total_size from v$pdbs;
CON_ID     NAME                           OPEN_MODE  TOTAL_SIZE
---------- ------------------------------ ---------- ----------
 2         PDB$SEED                       READ ONLY  283115520
 3         PDB1                           READ WRITE 393216000
 4         PDBTEST                        MOUNTED            0
 5         PDB2                           READ ONLY  393216000

****************************************************************************

Common Users & SYSDBA with #Oracle 12c Multitenancy

A 12c multitenant database introduces the new concept of local users and common users. This article shows simple use cases why DBAs may want to create common users – in contrast to the common users that are created automatically, like SYS, SYSTEM, MDSYS etc.

A typical requirement is to have a superuser other than SYS, but with the same power. Like the common user C##_SYS in the picture below.

Or suppose we have many pluggable databases (PDBs) and different superusers responsible for different PDBs like C##_ADMIN1 and C##_ADMIN2:

Common Users in Oracle 12cLet’s implement it as above. Initially, my demo environment looks like this:


SQL> select name,open_mode,con_id from v$pdbs;

NAME                           OPEN_MODE      CON_ID
------------------------------ ---------- ----------
PDB$SEED                       READ ONLY           2
PDB1                           READ WRITE          3
PDB2                           READ WRITE          4
PDB3                           READ WRITE          5

SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM     CON_ID
------------------------------ ----- ----- ----- ----- ----- ----- ----------
SYS                            TRUE  TRUE  FALSE FALSE FALSE FALSE          0
SYSDG                          FALSE FALSE FALSE FALSE TRUE  FALSE          1
SYSBACKUP                      FALSE FALSE FALSE TRUE  FALSE FALSE          1
SYSKM                          FALSE FALSE FALSE FALSE FALSE TRUE           1
At first, I create C##_SYS and grant SYSDBA as a common privilege to that new user:

SQL> create user c##_sys identified by oracle container=all;

User created.

SQL> grant sysdba to c##_sys container=all;

Grant succeeded.

SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM     CON_ID
------------------------------ ----- ----- ----- ----- ----- ----- ----------
SYS                            TRUE  TRUE  FALSE FALSE FALSE FALSE          0
SYSDG                          FALSE FALSE FALSE FALSE TRUE  FALSE          1
SYSBACKUP                      FALSE FALSE FALSE TRUE  FALSE FALSE          1
SYSKM                          FALSE FALSE FALSE FALSE FALSE TRUE           1
C##_SYS                        TRUE  FALSE FALSE FALSE FALSE FALSE          0
C##_SYS can now do anything to any PDB:

SQL> connect c##_sys/oracle@edd2r6p0/pdb1 as sysdba
Connected.
SQL> shutdown immediate
Pluggable Database closed.
SQL> connect / as sysdba
Connected.
SQL> select name,open_mode,con_id from v$pdbs;

NAME                           OPEN_MODE      CON_ID
------------------------------ ---------- ----------
PDB$SEED                       READ ONLY           2
PDB1                           MOUNTED             3
PDB2                           READ WRITE          4
PDB3                           READ WRITE          5

SQL> connect c##_sys/oracle@edd2r6p0/pdb1 as sysdba
Connected.
SQL> startup
Pluggable Database opened.
SQL> connect / as sysdba
Connected.
SQL> select name,open_mode,con_id from v$pdbs;

NAME                           OPEN_MODE      CON_ID
------------------------------ ---------- ----------
PDB$SEED                       READ ONLY           2
PDB1                           READ WRITE          3
PDB2                           READ WRITE          4
PDB3                           READ WRITE          5

Notice that there is a subtle difference in granting SYSDBA of the container database (CDB) as local or common privilege:

SQL> revoke sysdba from c##_sys container=all;

Revoke succeeded.

SQL> grant sysdba to c##_sys;

Grant succeeded.

SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM     CON_ID
------------------------------ ----- ----- ----- ----- ----- ----- ----------
SYS                            TRUE  TRUE  FALSE FALSE FALSE FALSE          0
SYSDG                          FALSE FALSE FALSE FALSE TRUE  FALSE          1
SYSBACKUP                      FALSE FALSE FALSE TRUE  FALSE FALSE          1
SYSKM                          FALSE FALSE FALSE FALSE FALSE TRUE           1
C##_SYS                        TRUE  FALSE FALSE FALSE FALSE FALSE          1

SQL> connect c##_sys/oracle@edd2r6p0/pdb1 as sysdba
ERROR:
ORA-01031: insufficient privileges


Warning: You are no longer connected to ORACLE.

C##_SYS has SYSDBA of the CDB “only”, therefore the error. Although:

SQL> connect c##_sys/oracle as sysdba
Connected.

SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT

SQL> alter session set container=pdb1;

Session altered.

SQL> shutdown immediate
Pluggable Database closed.

SQL> show con_name

CON_NAME
------------------------------
PDB1
SQL> startup
Pluggable Database opened.
SQL> connect c##_sys/oracle as sysdba
Connected.
SQL> select name,open_mode,con_id from v$pdbs;

NAME                           OPEN_MODE      CON_ID
------------------------------ ---------- ----------
PDB$SEED                       READ ONLY           2
PDB1                           READ WRITE          3
PDB2                           READ WRITE          4
PDB3                           READ WRITE          5
However, the proper way is probably granting it as a common privilege:

SQL> revoke sysdba from c##_sys;

Revoke succeeded.

SQL> grant sysdba to c##_sys container=all;

Grant succeeded.
Now to the implementation of C##_ADMIN1 and C##_ADMIN2. The point is here, that SYSDBA can be granted as a local privilege for certain PDBs only, to the effect that different superusers can be responsible for different groups of PDBs:

SQL> create user c##_admin1 identified by oracle container=all;

User created.

SQL> alter session set container=pdb1;

Session altered.

SQL> grant sysdba to c##_admin1 container=current;

Grant succeeded.

SQL> connect / as sysdba
Connected.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM     CON_ID
------------------------------ ----- ----- ----- ----- ----- ----- ----------
SYS                            TRUE  TRUE  FALSE FALSE FALSE FALSE          0
SYSDG                          FALSE FALSE FALSE FALSE TRUE  FALSE          1
SYSBACKUP                      FALSE FALSE FALSE TRUE  FALSE FALSE          1
SYSKM                          FALSE FALSE FALSE FALSE FALSE TRUE           1
C##_SYS                        TRUE  FALSE FALSE FALSE FALSE FALSE          0
C##_ADMIN1                     TRUE  FALSE FALSE FALSE FALSE FALSE          3

6 rows selected.


For now, C##_ADMIN1 can only connect to PDB1:

SQL> connect c##_admin1/oracle@edd2r6p0/pdb1 as sysdba
Connected.
SQL> select count(*) from session_privs;

  COUNT(*)
----------
       233

SQL> connect c##_admin1/oracle@edd2r6p0/pdb2 as sysdba
ERROR:
ORA-01017: invalid username/password; logon denied


Warning: You are no longer connected to ORACLE.
The completed implementation of the picture above:

SQL> connect / as sysdba
Connected.
SQL> alter session set container=pdb2;

Session altered.

SQL> grant sysdba to c##_admin1 container=current;

Grant succeeded.

SQL> connect / as sysdba
Connected.
SQL> create user c##_admin2 identified by oracle;

User created.

SQL> alter session set container=pdb3;

Session altered.

SQL> grant sysdba to c##_admin2 container=current;

Grant succeeded.

SQL> connect / as sysdba
Connected.


SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM     CON_ID
------------------------------ ----- ----- ----- ----- ----- ----- ----------
SYS                            TRUE  TRUE  FALSE FALSE FALSE FALSE          0
SYSDG                          FALSE FALSE FALSE FALSE TRUE  FALSE          1
SYSBACKUP                      FALSE FALSE FALSE TRUE  FALSE FALSE          1
SYSKM                          FALSE FALSE FALSE FALSE FALSE TRUE           1
C##_SYS                        TRUE  FALSE FALSE FALSE FALSE FALSE          0
C##_ADMIN1                     TRUE  FALSE FALSE FALSE FALSE FALSE          3
C##_ADMIN1                     TRUE  FALSE FALSE FALSE FALSE FALSE          4
C##_ADMIN2                     TRUE  FALSE FALSE FALSE FALSE FALSE          5

8 rows selected.

sqlplus: error while loading shared libraries: libsqlplus.so: cannot open shared object file: No such file o

[oracle@sujeet~]$ sqlplus / as sysdba
sqlplus: error while loading shared libraries: libsqlplus.so: cannot open shared object file: No such file o    

Solution:-

I did solve this error by setting

[oracle@sujeet ~]$
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib:$ORACLE_HOME

[oracle@sujeet ~]$ sqlplus / as sysdba


SQL> select name from v$database;

NAME
---------

Airtel

ERROR 1396 (HY000): Operation ALTER USER failed for 'Mysql'@'%'

 This MySQL error — ERROR 1396 (HY000): Operation ALTER USER failed for 'Mysql'@'%' — means that MySQL cannot find the user ...