ACE Director Alum Daniel Morgan, founder of Morgan's Library, is scheduling
complimentary technical Workshops on Database Security for the first 30
Oracle Database customers located anywhere in North America, EMEA, LATAM, or
APAC that send an email to
asra_us@oracle.com. Request a Workshop for
your organization today.
Purpose
Application containers provide significant
advantages over the original Container Database architecture introduced in
version 12.1 by adding a third logical layer between the root container
and the PDB.
conn sys@orabase as sysdba
Enter password:
Connected.
sho con_id
CON_ID
------------------------------
1
show con_name
CON_NAME
------------------------------
CDB$ROOT
SELECT name, open_mode, application_root,
application_pdb, application_seed, pdb_count
FROM v$containers
ORDER BY con_id;
NAME OPEN_MODE APP
APP APP PDB_COUNT
---------- ---------- --- --- --- ----------
CDB$ROOT READ WRITE NO NO NO 2
PDB$SEED READ ONLY NO NO NO 0
PDBDEV READ WRITE NO NO NO 0
-- as desirable as it would be to do so you cannot use special characters in a PDB name
CREATE PLUGGABLE DATABASE uwapp_root AS APPLICATION CONTAINER
ADMIN USER uwAdmin IDENTIFIED BY uwAdmin
ROLES = (CDB_DBA)
DEFAULT TABLESPACE uwapp_tbs
FILE_NAME_CONVERT = ('/pdbseed/', '/uwapp/')
USER_TABLESPACES = NONE
LOGGING;
Pluggable database created.
SELECT name, open_mode, application_root,
application_pdb, application_seed, pdb_count
FROM v$containers
ORDER BY con_id;
NAME OPEN_MODE APP
APP APP PDB_COUNT
---------- ---------- --- --- --- ----------
CDB$ROOT READ WRITE NO NO NO 3
PDB$SEED READ ONLY NO NO NO 0
PDBDEV READ WRITE NO NO NO 0
UWAPP_ROOT MOUNTED YES NO NO 0
ALTER PLUGGABLE DATABASE uwapp_root OPEN;
Pluggable database altered.
SELECT name, creation_date, clb_goal, pdb
FROM v$services
ORDER BY 1;
NAME CREATION_DATE CLB_G PDB
--------------- -------------------- ----- ------------
SYS$BACKGROUND 26-JAN-2017 13:54:44 SHORT CDB$ROOT
SYS$USERS 26-JAN-2017 13:54:44 SHORT CDB$ROOT
uwapp_root 26-MAR-2017 17:09:28 LONG UWAPP$ROOT
pdbdev 02-MAR-2017 07:57:37 LONG PDBDEV
orabase 02-MAR-2017 07:52:46 LONG CDB$ROOT
orabaseXDB 02-MAR-2017 07:52:46 LONG CDB$ROOT
-- to access the application root container directly you must, manually, create an entry in TNSNAMES.ORA
Alter Application: Application Installation
ALTER PLUGGABLE DATABASE APPLICATION
{ { app_name
{ BEGIN INSTALL 'app_version' [ COMMENT 'comment' ]
| END INSTALL [ 'app_version' ]
| BEGIN PATCH number [ MINIMUM VERSION 'app_version' ] [ COMMENT 'comment' ]
| END PATCH [ number ]
| BEGIN UPGRADE 'start_app_version' TO 'end_app_version' [ COMMENT 'comment' ]
| END UPGRADE [ TO 'end_app_version' ]
| BEGIN UNINSTALL
| END UNINSTALL
| SET PATCH number
| SET VERSION 'app_version'
| SET COMPATIBILITY VERSION { 'app_version' | CURRENT }
| SYNC }
|
{ ALL SYNC }
}
conn sys@orabase as sysdba
Enter password:
Connected.
ALTER PLUGGABLE DATABASE APPLICATION uw_app BEGIN INSTALL '1.0';
Pluggable database altered.
CREATE TABLESPACE uwapp_tbs
DATAFILE '/u01/app/oracle/oradata/orcl12c/uwapp/uwapp_tbs'
SIZE 25M AUTOEXTEND ON NEXT 25M;
Tablespace created.
-- create user
CREATE USER uwapp_user IDENTIFIED BY uwapp_user
DEFAULT TABLESPACE uwapp_tbs
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON uwapp_tbs;
User created.
GRANT create session TO uwapp_owner;
GRANT create procedure TO uwapp_owner
GRANT create table TO uwapp_owner;
GRANT create view TO uwapp_owner;
Grant succeeded.
CREATE OR REPLACE PROCEDURE uwapp_owner.who_am_i AUTHID DEFINER IS
BEGIN
dbms_output.put_line('I do not know');
END who_am_i;
/
CREATE TABLE uwapp_owner.t1 (
tid NUMBER(10),
last_name VARCHAR2(20));
ALTER TABLE uwapp_owner.t1
ADD PRIMARY KEY (tid);
CREATE TABLE uwapp_owner.t2(
tid NUMBER(10),
last_name VARCHAR2(20));
ALTER TABLE uwapp_owner.t2
ADD PRIMARY KEY (tid);
CREATE VIEW uwapp_owner.t1t2_view AS
SELECT t1.tid, t2.last_name
FROM uwapp_user.t1, uwapp_user.t2
WHERE t1.tid = t2.tid;
INSERT INTO uwapp_owner.t1 VALUES (1, 'MORGAN');
INSERT INTO uwapp_owner.t1 VALUES (2, 'KYTE');
INSERT INTO uwapp_owner.t1 VALUES (3, 'LEWIS');
INSERT INTO uwapp_owner.t2 VALUES (1, 'TOWNSEND');
INSERT INTO uwapp_owner.t2 VALUES (2, 'KURIAN');
COMMIT;
SELECT * FROM uwapp_user.t1t2_view;
SQL> SELECT * FROM uwapp_user.t1t2_view;
TID LAST_NAME
---------- --------------------
1 TOWNSEND
2 KURIAN
ALTER PLUGGABLE DATABASE APPLICATION uw_app END INSTALL;
Pluggable database altered.
ALTER PLUGGABLE DATABASE SAVE STATE;
Pluggable database altered.
col app_name format a10
col app_version format a12
SELECT app_name, app_version, app_status, app_implicit
FROM dba_applications
WHERE app_name = 'UW_APP';
APP_NAME APP_VERSION APP_STATUS A
---------- ------------ ------------ -
UW_APP 1.0 NORMAL N
/* if there are application PDBs, under the application root container, exit synchronize them with their root the instructions for doing so can be found below under ALTER APPLICATION PDB */
Alter Application Container and add a
SHARABLE Object after the initial installation is completed
ALTER PLUGGABLE DATABASE APPLICATION <application_name>
BEGIN UPGRADE '<existing_verison_number>' TO '<new_version_number>'
COMMENT '<upgrade_description';
ALTER PLUGGABLE DATABASE APPLICATION <application_name>_app END UPGRADE;
NAME TYPE VALUE
---------------- ----------- ---------
default_sharing string METADATA
SQL> ALTER PLUGGABLE DATABASE APPLICATION uw_app BEGIN INSTALL '1.0';
ALTER PLUGGABLE DATABASE APPLICATION uw_app BEGIN INSTALL '1.0'
*
ERROR at line 1:
ORA-65221: application UW_APP exists already
SQL> ALTER PLUGGABLE DATABASE APPLICATION uw_app
2 BEGIN UPGRADE '1.0' TO '2.0'
3 COMMENT 'Adding New Table With Sharing';
SQL> ALTER PLUGGABLE DATABASE APPLICATION uw_app END UPGRADE;
SQL desc dba_applications
SQL> desc dba_applications
Name Null? Type
----------------------- -------- --------------
APP_NAME VARCHAR2(128)
APP_ID NUMBER
APP_VERSION VARCHAR2(30)
APP_STATUS VARCHAR2(12)
APP_IMPLICIT VARCHAR2(1)
APP_CAPTURE_SERVICE VARCHAR2(64)
APP_CAPTURE_MODULE VARCHAR2(64)
col app_name format a37
SQL> SELECT app_name, app_id, app_version, app_status, app_implicit
2 FROM dba_applications;
APP_NAME APP_ID APP_VERSION APP_STATUS A
------------------------------------- ------- ------------ ------------ -
APP$4BAF1A01C5964D55E0530100007F821B 2 1.0 NORMAL Y
UW_APP 21 2.0 NORMAL N
Change the status of an Application Root container
ALTER PLUGGABLE DATABASE <application_root_container_name> <CLOSE | OPEN [<READ ONLY | READ WRITE>]>
ALTER SESSION SET CONTINER = CDB$ROOT;
ALTER PLUGGABLE DATABASE uwapp_root CLOSE;
Drop Application Root
DROP PLUGGABLE DATABASE <application_root_container_name> INCLUDING DATAFILES;
ALTER SESSION SET CONTINER = CDB$ROOT;
ALTER PLUGGABLE DATABASE uwapp_root CLOSE;
DROP PLUGGABLE DATABASE uwapp_root INCLUDING DATAFILES;
Application Seed
Notes
Prerequisites must be met before creating an application seed.
- The application root to which the application seed must be read/write
The current user must be a common user
The current user must have the CREATE PLUGGABLE DATABASE system priv
The application must be installed in the application root
Create an application seed from the application root
CREATE PLUGGABLE DATABASE AS SEED FROM <application_root_container>
[<file_name_convert_clause>]
[LOGGING | NOLOGGING];
CREATE PLUGGABLE DATABASE AS SEED
ADMIN USER uwappAdmin IDENTIFIED BY uwappAdmin
FILE_NAME_CONVERT = ('/uwapp/', '/uwappseed/')
LOGGING;
CREATE PLUGGABLE DATABASE AS SEED
*
ERROR at line 1:
ORA-65005: missing or invalid file name pattern for file - /u01/app/oracle/oradata/orcl12c/pdbseed/system01.dbf
CREATE PLUUGABLE DATABASE AS SEED
ADMIN USER uwappAdmin IDENTIFIED BY uwappAdmin
FILE_NAME_CONVERT = ('/pdbseed/', '/uwappseed/')
LOGGING;
Pluggable database created.
SELECT name, open_mode
FROM v$containers;
NAME OPEN_MODE
------------------------------ ----------
UWAPP_ROOT READ WRITE
UWAPP_ROOT$SEED MOUNTED
ALTER PLUGGABLE DATABASE uwapp_root$seed OPEN;
Pluggable database altered.
ALTER PLUGGABLE DATABASE uwapp_root$seed CLOSE;
Pluggable database altered.
ALTER PLUGGABLE DATABASE uwapp_root$seed OPEN READ ONLY;
Pluggable database altered.
Create an application seed from the application root: FAIL
CREATE PLUGGABLE DATABASE AS SEED FROM uwapp_root
ADMIN USER uwappAdmin IDENTIFIED BY uwappAdmin
FILE_NAME_CONVERT = ('/pdbseed/', '/uwappseed/')
LOGGING;
SQL> SELECT con_id, name, open_mode, application_root, application_pdb, application_seed
2 FROM v$containers
3 ORDER BY con_id;
CON_ID NAME OPEN_MODE APP
APP APP
------- ---------------- ----------- --- --- ---
4 UWAPP_ROOT READ WRITE YES NO NO
6 UWAPP_ROOT$SEED MOUNTED NO YES YES
SQL> ALTER PLUGGABLE DATABASE uwapp_root$seed OPEN;
Warning: PDB altered with errors.
SQL> ALTER PLUGGABLE DATABASE uwapp_root$seed OPEN READ ONLY;
Warning: PDB altered with errors.
SQL> host
[oracle@vbgeneric ~]$ cd $ORACLE_BASE/diag/orabase/orabase/trace
[oracle@vbgeneric trace]$ tail alert_orabase.log
UWAPP_ROOT$SEED(6):Opatch validation is skipped for PDB UWAPP_ROOT$SEED (con_id=0)
UWAPP_ROOT$SEED(6):***************************************************************
UWAPP_ROOT$SEED(6):WARNING: Pluggable Database UWAPP_ROOT$SEED with pdb id - 6 is
UWAPP_ROOT$SEED(6): altered with errors or warnings. Please look into
UWAPP_ROOT$SEED(6): PDB_PLUG_IN_VIOLATIONS view for more details.
UWAPP_ROOT$SEED(6):***************************************************************
2017-04-19T18:45:58.662039-04:00
UWAPP_ROOT$SEED(6):Opening pdb with no Resource Manager plan active
Pluggable database UWAPP_ROOT$SEED opened read only
UWAPP_ROOT(4):Completed: ALTER PLUGGABLE DATABASE uwapp_root$seed OPEN READ ONLY
[oracle@vbgeneric ~]$exit
SQL> col time format a29
SQL> col name format a16
SQL> col type format a6
SQL> col cause format a30
SQL> col action format a22
SQL> SELECT time, name, cause, status, action
2* FROM pdb_plug_in_violations;
TIME NAME CAUSE STATUS ACTION
----------------------------- ---------------- --------------------------------------- -------- ----------------------
19-APR-17 06.45.57.958082 PM UWAPP_ROOT$SEED Non-Application PDB to Application PDB PENDING Run pdb_to_apppdb.sql.
SQL> @?/rdbms/admin/pdb_to_apppdb.sql
SQL> SET FEEDBACK 1
SQL> SET NUMWIDTH 10
SQL> SET LINESIZE 80
SQL> SET TRIMSPOOL ON
SQL> SET TAB OFF
SQL> SET PAGESIZE 100
SQL>
SQL> WHENEVER SQLERROR EXIT;
SQL>
SQL> VARIABLE cdbname VARCHAR2(128)
SQL> VARIABLE pdbname VARCHAR2(128)
SQL> VARIABLE appname VARCHAR2(128)
SQL> BEGIN
2 -- Disallow script in non-CDB
3 SELECT sys_context('USERENV', 'CDB_NAME')
4 INTO :cdbname
5 FROM dual
6 WHERE sys_context('USERENV', 'CDB_NAME') is not null;
7 -- Disallow script in CDB Root
8 -- Disallow script in PDB$SEED (Bug 22550952)
9 SELECT sys_context('USERENV', 'CON_NAME')
10 INTO :pdbname
11 FROM dual
12 WHERE sys_context('USERENV', 'CON_NAME') <> 'CDB$ROOT'
13 AND sys_context('USERENV', 'CON_NAME') <> 'PDB$SEED';
14 -- Disallow script outside of Application Container
15 SELECT sys_context('USERENV', 'APPLICATION_NAME')
16 INTO :appname
17 FROM dual
18 WHERE sys_context('USERENV', 'APPLICATION_NAME') is not null;
19 -- Disallow script in Proxy PDB (Bug 22550952). This query works
20 -- because remote mapping in Proxy PDB has been disabled using
21 -- the underscore parameter.
22 SELECT /*+ OPT_PARAM('_ENABLE_VIEW_PDB', 'FALSE') */ name
23 INTO :pdbname
24 FROM v$pdbs
25 WHERE proxy_pdb='NO';
26 END;
27 /
BEGIN
*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 22
Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
[oracle@vbgeneric ~]$
-- upon dissecting the pdb_to_apppdb.sql script the following was found to be the root cause of the error
SQL> SELECT /*+ OPT_PARAM('_ENABLE_VIEW_PDB', 'FALSE') */ name
2 FROM v$pdbs
3 WHERE proxy_pdb='NO';
NAME
------------------------------
UWAPP_ROOT
UWAPP_ROOT$SEED
-- an SR has been opened with Oracle and we are awaiting a resolution but the next line of code is a classic
select TO_NUMBER('NOT_IN_APPLICATION_PDB') from v$pdbs
where con_id=sys_context('USERENV', 'CON_ID') and application_pdb<>'YES';
-- The script is 100% guaranteed to fail when it tries to cast the string as a number.
SQL> SELECT con_id, name, open_mode, pdb_count
2 FROM v$containers
3 ORDER BY 1;
CON_ID NAME OPEN_MODE PDB_COUNT
------- --------------- ---------- ----------
1 CDB$ROOT READ WRITE 2
2 PDB$SEED READ ONLY 0
3 ORCL READ WRITE 0
4 UWAPP_ROOT READ WRITE 0
5 F797079713_21_1 READ ONLY 0
6 UWAPP_ROOT$SEED READ ONLY 0
Exhausting All The Options
The following fails, fails, and fails, but I thought it important to try every possibility before opening the inevitable SR.
-- try synchronizing from CDB$ROOT SQL> sho con_id
CON_ID
------------------------------
1
SQL> alter session set "_skip_app_unconverted_check" = TRUE;
Session altered.
SQL> alter pluggable database application all sync;
alter pluggable database application all sync
*
ERROR at line 1:
ORA-65046: operation not allowed from outside a pluggable database
-- well I am in a container database, not a pluggable so I'll give this one to Oracle development.
-- try synchronizing from the application root
SQL> alter session set container=UWAPP_ROOT;
Session altered.
SQL> alter session set "_skip_app_unconverted_check" = TRUE;
Session altered.
SQL> alter pluggable database application all sync;
alter pluggable database application all sync
*
ERROR at line 1:
ORA-65272: operation not allowed from outside an application PDB
-- I am absolutely in an application container but perhaps the root is not considered a "PDB" by some definition.
SQL> alter session set container=UWAPP_ROOT$SEED;
Session altered.
SQL> alter session set "_skip_app_unconverted_check" = TRUE;
Session altered.
SQL> alter pluggable database application all sync;
alter pluggable database application all sync
*
ERROR at line 1:
ORA-16000: database or pluggable database open for read-only access
-- this leaves two possibilities only ... closed and open read write
SQL> alter pluggable database uwapp_root$seed close;
Pluggable database altered.
SQL> alter session set "_skip_app_unconverted_check" = TRUE;
Session altered.
SQL> alter pluggable database application all sync;
alter pluggable database application all sync
*
ERROR at line 1:
ORA-65290: Application may not be altered.
-- clearly closed is not the correct answer.
SQL> alter pluggable database uwapp_root$seed open;
Warning: PDB altered with errors.
SQL> alter session set "_skip_app_unconverted_check" = TRUE;
Session altered.
SQL> alter pluggable database application all sync;
Pluggable database altered.
SQL> alter session set "_skip_app_unconverted_check" = FALSE;
Session altered.
-- Couldn't the original message said "you must be in an application PDB in read write mode"? Yes it could have but why make it easy for us?
-- where I stopped I proved that the application container's objects and tablespaces are not in the application seed.
Drop Application Seed
DROP PLUGGABLE DATABASE <pdb_name> [INCLUDING DATAFILES];
SQL> ALTER SESSION SET CONTAINER = uwapp_root;
SQL> ALTER PLUGGABLE DATABASE uwapp_root$seed CLOSE;
Pluggable database altered.
SQL> DROP PLUGGABLE DATABASE uwapp_root$seed INCLUDING DATAFILES;
Pluggable database dropped.
PDBs Under Application Root
Create PDB from Applications Root
CREATE PLUGGABLE DATABASE <PDB_name>
ADMIN USER <admin_user_name> IDENTIFIED BY <admin_user_password>;
conn sys@orabase as sysdba
Enter password:
Connected.
SELECT name, open_mode, application_root, application_pdb, application_seed
FROM v$containers
WHERE application_root = 'YES'
ORDER BY 1;
NAME OPEN_MODE APP APP APP
-------------- ---------- --- --- ---
APPROOT_UW MOUNTED YES NO NO
ALTER SESSION SET CONTAINER=approot_uw;
CREATE PLUGGABLE DATABASE uwapp_dev1
ADMIN USER uw_pdb_admin IDENTIFIED BY uwAdmin;
ALTER PLUGGABLE DATABASE uwapp_dev1OPEN;
-- I want to specify the file location
ALTER SESSION SET CONTAINER = uwapp_dev1;
ALTER PLUGGABLE DATABASE APPLICATION uwapp_dev1 SYNC;
Create PDB from Applications Seed
Alter Application PDB
ALTER PLUGGABLE DATABASE <pdb_name> SYNC;
conn sys@orabase as sysdba
Enter password:
Connected.
ALTER SESSION SET container = uwapp_dev1;
sho con_name
???
-- Check for application schema objects and data
desc ref_app_user.reference_data;
ERROR:
ORA-04043: object ref_app_user.reference_data does not exist
ALTER PLUGGABLE DATABASE uwapp_dev1 SYNC;
-- Check for application schema objects and data
desc ref_app_user.reference_data;
SELECT c.name,
aps.con_uid,
aps.app_name,
aps.app_version,
aps.app_status
FROM dba_app_pdb_status aps
JOIN v$containers c ON c.con_uid = aps.con_uid
WHERE aps.app_name = 'REF_APP';
NAME CON_UID APP_NAME APP_VERSIO APP_STATUS
-------------------- ---------- -------------------- ---------- ------------
APPPDB1 4291055883 REF_APP 1.0 NORMAL
Drop Application Seed
DROP PLUGGABLE DATABASE <container_name> [INCLUDING DATAFILES];
conn sys@orabase as sysdba
Enter password:
Connected.
ALTER SESSION SET container = approot_uw;
ALTER PLUGGABLE DATABASE uwapp_dev1 CLOSE;
DROP PLUGGABLE DATABASE uwapp_dev1 INCLUDING DATAFILES;