One of the new multitenancy related features in Oracle 12c Release 2 is Application Containers.
In 12c Release 1, we could have a Container database (CDB) host a number of optional pluggable databases or PDBs. Now in 12.2.0.1, the multitenancy feature has been enhanced further and we can now have not only CDBs and PDBs but also have another component called an Application Container which in essence is a hybrid of a CDB and a PDB.
So now in 12.2.0.1, a CDB can contain (optionally) user created Application Containers and then Application Containers can in turn host one or more PDBs.
For example, an Application Container can contain a number of PDBs which contain individual sales data of different regions, but at the same time can share what are called common objects.
Maybe each region’s PDB has data just for that region, but the table structure is the same regardless of the region. In that case the table definition (or metadata) is stored in the application container accessible to all the PDBs hosted by that application container. If any changes are required to be made for application tables, then that DDL change need only be made once in the central application container and that change will then be visible to all the PDBs hosted by that application container.
Or there are some tables which are common to all the PDBs – some kind of master data maybe. And rather than have to store this common data in each individual PDB (as was the case in 12.1.0.2), we just store it once in a central location which is the application container and then that data is visible to all the hosted PDBs.
In other words, an application container functions as an application specific CDB within a CDB.
Think of a Software as a Service (SaaS) deployment model where we are hosting a number of customers and each customer has its own individual data which needs to be stored securely in a separate database but at the same time we need to share some metadata or data which is common to all the customers.
Let’s have a look a simple example of 12c Release 2 Application Containers at work.
The basic steps are:
- Create the Application Container
- Create the Pluggable Databases
- Install the Application
- After installing the application, synchronize the pluggable databases with the application container root so that any changes in terms of DDL or DML made by the application are now visible to all hosted pluggable databases
- Optionally upgrade or deinstall the application
Create the Application Container
SQL> CREATE PLUGGABLE DATABASE appcon1 AS APPLICATION CONTAINER ADMIN USER appadm IDENTIFIED BY oracle
FILE_NAME_CONVERT=('/u03/app/oradata/cdb1/pdbseed/','/u03/app/oradata/cdb1/appcon1/');
Pluggable database created.
Create the Pluggable Databases which are to be hosted by the Application Container by connecting to the application container root
SQL> alter session set container=appcon1;
Session altered.
SQL> alter pluggable database open;
Pluggable database altered.
SQL> CREATE PLUGGABLE DATABASE pdbhr1 ADMIN USER pdbhr1_adm IDENTIFIED BY oracle
FILE_NAME_CONVERT=('/u03/app/oradata/cdb1/pdbseed/','/u03/app/oradata/cdb1/appcon1/pdbhr1/');
Pluggable database created.
SQL> SQL> CREATE PLUGGABLE DATABASE pdbhr2 ADMIN USER pdbhr2_adm IDENTIFIED BY oracle
FILE_NAME_CONVERT=('/u03/app/oradata/cdb1/pdbseed/','/u03/app/oradata/cdb1/appcon1/pdbhr2/');
Pluggable database created.
SQL> SQL> alter pluggable database all open;
Pluggable database altered.
Install the application
In the first example we will be seeing how some common data is being shared among all the pluggable databases. Note the keyword SHARING=DATA.
SQL> alter pluggable database application region_app begin install '1.0';
Pluggable database altered.
SQL> create user app_owner identified by oracle;
User created.
SQL> grant connect,resource,unlimited tablespace to app_Owner;
Grant succeeded.
SQL> create table app_owner.regions
2 sharing=data
3 (region_id number, region_name varchar2(20));
Table created.
SQL> insert into app_owner.regions
2 values (1,'North');
1 row created.
SQL> insert into app_owner.regions
2 values (2,'South');
1 row created.
SQL> commit;
Commit complete.
SQL> alter pluggable database application region_app end install '1.0';
Pluggable database altered.
View information about Application Containers via the DBA_APPLICATIONS view
SQL> select app_name,app_status from dba_applications;
APP_NAME
--------------------------------------------------------------------------------
APP_STATUS
------------
APP$4BDAAF8836A20F9CE053650AA8C0AF21
NORMAL
REGION_APP
NORMAL
Synchronize the pluggable databases with the application root
Note that until this is done, changes made by the application install are not visible to the hosted PDBs.
SQL> alter session set container=pdbhr1;
Session altered.
SQL> select * from app_owner.regions;
select * from app_owner.regions
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> alter pluggable database application region_app sync;
Pluggable database altered.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 North
2 South
SQL> alter session set container=pdbhr2;
Session altered.
SQL> alter pluggable database application region_app sync;
Pluggable database altered.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 North
2 South
Note that any direct DDL or DML is not permitted in this case
SQL> drop table app_owner.regions;
drop table app_owner.regions
*
ERROR at line 1:
ORA-65274: operation not allowed from outside an application action
SQL> insert into app_owner.regions values (3,'East');
insert into app_owner.regions values (3,'East')
*
ERROR at line 1:
ORA-65097: DML into a data link table is outside an application action
Let us now upgrade the application we just created and create the same application table, but this time with the keyword SHARING=METADATA
SQL> alter pluggable database application region_app begin upgrade '1.0' to '1.1';
Pluggable database altered.
SQL> select app_name,app_status from dba_applications;
APP_NAME
--------------------------------------------------------------------------------
APP_STATUS
------------
APP$4BDAAF8836A20F9CE053650AA8C0AF21
NORMAL
REGION_APP
UPGRADING
SQL> drop table app_owner.regions;
Table dropped.
SQL> create table app_owner.regions
2 sharing=metadata
3 (region_id number,region_name varchar2(20));
Table created.
SQL> alter pluggable database application region_app end upgrade;
Pluggable database altered.
We can now see that the table definition is the same in both the PDBs, but each PDB can now insert its own individual data in the table.
SQL> alter session set container=pdbhr1;
Session altered.
SQL> alter pluggable database application region_app sync;
Pluggable database altered.
SQL> desc app_owner.regions
Name Null? Type
----------------------------------------- -------- ----------------------------
REGION_ID NUMBER
REGION_NAME VARCHAR2(20)
SQL> insert into app_owner.regions
2 values (1,'North');
1 row created.
SQL> insert into app_owner.regions
2 values (2,'North-East');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 North
2 North-East
SQL> alter session set container=pdbhr2;
Session altered.
SQL> alter pluggable database application region_app sync;
Pluggable database altered.
SQL> desc app_owner.regions
Name Null? Type
----------------------------------------- -------- ----------------------------
REGION_ID NUMBER
REGION_NAME VARCHAR2(20)
SQL> select * from app_owner.regions;
no rows selected
SQL> insert into app_owner.regions
2 values (1,'South');
1 row created.
SQL> insert into app_owner.regions
2 values (2,'South-East');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 South
2 South-East
While DML activity was permitted in this case, still any DDL activity is not permitted.
SQL> drop table app_owner.regions;
drop table app_owner.regions
*
ERROR at line 1:
ORA-65274: operation not allowed from outside an application action
SQL> alter table app_owner.regions
2 add (region_location varchar2(10));
alter table app_owner.regions
*
ERROR at line 1:
ORA-65274: operation not allowed from outside an application action
We will now perform another upgrade to the application and this time note the keyword SHARING=EXTENDED DATA. In this case while some portion of the data is common and shared among all the PDBs, the individual PDBs can still have the flexibility to have additional data specific to that PDB stored in the table along with the common data which is the same for all the PDBs.
SQL> alter session set container=appcon1;
Session altered.
SQL> alter pluggable database application region_app begin upgrade '1.1' to '1.2';
Pluggable database altered.
SQL> drop table app_owner.regions;
Table dropped.
SQL> create table app_owner.regions
2 sharing=extended data
3 (region_id number,region_name varchar2(20));
Table created.
SQL> insert into app_owner.regions
2 values (1,'North');
1 row created.
SQL> commit;
Commit complete.
SQL> alter pluggable database application region_app end upgrade;
Pluggable database altered.
Note that the PDBs share some common data, but individual PDB can insert its own data.
SQL> alter session set container=pdbhr1;
Session altered.
SQL> alter pluggable database application region_app sync;
Pluggable database altered.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 North
SQL> insert into app_owner.regions
2 values
3 (2,'North-West');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 North
2 North-West
SQL> alter session set container=pdbhr2;
Session altered.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 South
2 South-East
SQL> alter pluggable database application region_app sync;
Pluggable database altered.
SQL> select * from app_owner.regions;
REGION_ID REGION_NAME
---------- --------------------
1 North