Met de introductie van Oracle Multitenant en hiermee pdb's vraagt het beheer van een oracle database extra handelingen. Zo is het rechtstreeks aanloggen aan een pdb op de ‘standaard’ manier van oracle omslachtig te noemen. Eerst moet geconnecteerd worden aan de cdb$root om daarna met een alter session naar de pdb te gaan.
[oracle@ab031 bin]$ export ORACLE_SID=CA919N2
[oracle@ab031 bin]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Oct 4 11:52:45 2023
Version 19.16.0.0.0
Copyright (c) 1982, 2022, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.16.0.0.0
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 D919NA READ WRITE NO
5 D919NB READ WRITE NO
SQL> alter session set container=D919NA;
Session altered.
SQL>
Er is een manier om rechtsreeks naar de pdb aan te loggan als sysdba door het definiëren van ORACLE_SID en ORACLE_PDB_SID .
[oracle@ab031 bin]$ export ORACLE_SID=CA919N2
[oracle@ab031 bin]$ export ORACLE_PDB_SID=D919NA
[oracle@ab031 bin]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Oct 4 11:57:47 2023
Version 19.16.0.0.0
Copyright (c) 1982, 2022, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.16.0.0.0
SQL> show con_name
CON_NAME
------------------------------
D919NA
SQL>
Dit is echter foutgevoelig, want als ORACLE_PDB_SID verwijst naar een niet bestaande pdb wordt er geen foutmelding gegeven en wordt je als sysdba geconnecteerd aan de cdb$root. Dit kan ernstige fouten veroorzaken. Eventuele aanpassingen worden dus niet de een pdb uitgevoerd maar in de cdb$root.
[oracle@ab031 bin]$ export ORACLE_SID=CA919N2
[oracle@ab031 bin]$ export ORACLE_PDB_SID=D919NC
[oracle@ab031 bin]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Oct 4 12:02:34 2023
Version 19.16.0.0.0
Copyright (c) 1982, 2022, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.16.0.0.0
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL>
Om zonder risico rechtstreeks te kunnen aanloggen aan de pdb (of cdb$root) is script sysdba gemaakt. Dit script maakt gebruik van de ‘standaard’ /etc/oratab file.
[oracle@ab031 bin]$ cat /etc/oratab
CA919N2:/u01/app/odaorahome/oracle/product/19.0.0.0/dbhome_1:N
[oracle@ab031 bin]$
Als extra file wordt file /etc/pdbtab aangemaakt . In onderstaand voorbeeld is er sprake van een CDB database CA919N2 met 2 pdbs; D919NA en D919NB.
[oracle@ab031 bin]$ cat /etc/pdbtab
# file:/etc/pdbtab
#
# This file is Ageos specific and made to continue using the NON-CDB tooling
#
# The different 'fields' are separated by a :
#
# 1st field: name of the database being searched for; db_name or pdb.
# 2nd field: name of the database or container used in /etc/oratab
# 3rd field: name of the instance (ORACLE_SID)
#
CA919N2:CA919N2:CA919N2
D919NA:CA919N2:CA919N2
D919NB:CA919N2:CA919N2
[oracle@ab031 bin]$ oraenv
De header van de file spreekt in principe voor zich.
sysdba. Om te connecteren naar de cdb$root is dit de db_name, of naam van de pdb als je rechtreeks naar de pdb wil connecteren./etc/oratab is opgenomen. Deze naam wordt ook gebruikt in oraenv vanuit het script.In het script wordt ook gebruik gemaakt van ORACLE_PDB_SID maar het script controleert ook of er uiteindelijk geconnecteerd wordt aan de gevraagde pdb als de parameter een pdb betreft. Een niet bestaande pdb geeft in dit scipt een foutmelding, waardoor je nooit ‘per ongeluk’ in de cdb$root terecht komt als er een nietbestaande pdb als parameter meegegeven wordt.
Het script ziet er als volgt uit:
#set -x
#!/bin/bash
#
# sysdba
# Version: 1.0.2 (2023-06-06)
# Written by Rene Geilings
#
# Purpose: sqlplus wrapper to connect to noncdb and pdb database as sysdba
#
# -----------------------------------------------------------------
# | A | B | C | A=B | B=C | action |ORA_PDB_SID|
# -----------------------------------------------------------------
# |CA919N1 |CA919N1 |CA919N1 |TRUE |TRUE |SIDB |NO |
# |D912NA |D912NA |D912NA |TRUE |TRUE |SIDB |NO |
# |CA919P |CA919P |CA919P1 |TRUE |FALSE |RACDB |NO |
# |D912P |D912P |D912P1 |TRUE |FALSE |RACDB |NO |
# |CA919P |CA919P |CA919P1 |TRUE |FALSE |RACCDB |NO |
# |D919P |CA919P |CA919P1 |FALSE |FALSE |RACPDB |YES |
# -----------------------------------------------------------------
#
############################################################################
display_usage () {
sn=$(basename -- "$0")
echo -e "\nThis script requires 1 argument: Oracle (pluggable) database to connect to as sysdba"
exit 1
}
function checkPDB () {
con_name="`$ORACLE_HOME/bin/sqlplus -s -L /nolog <<__EOF
set pages 0 serveroutput on feed off trimspool on
connect / as sysdba
select sys_context('userenv','CON_NAME') con_name from dual;
__EOF`"
if [ "${con_name}" == "${ORACLE_PDB_SID}" ]
then
CON=Y
else
echo "ERROR no pdb found"
CON=N
fi
}
#
FILE=/etc/pdbtab
if [ ! -f "$FILE" ]; then
echo "$FILE does not exist."
exit 1
fi
# call display_usage() function if cloned_DB not supplied
[[ $# -eq 0 ]] && display_usage
#DB=$(echo $1 | tr [:lower:] [:upper:])
DB=$1
#
# pdbtab vars
INP=$(cat /etc/pdbtab | grep -v ^[0-9] | grep -v ^# | sed '/^\s*$/d'|grep ^${DB}:)
if [ -z "$INP" ]
then
echo "no entry found for ${DB} in /etc/pdbtab"
exit 1
fi
DBSNAME=$(echo ${INP}|cut -d':' -f1)
DB_NAME=$(echo ${INP}|cut -d':' -f2)
INAME=$(echo ${INP}|cut -d':' -f3)
[ "${DBSNAME}" == "${DB_NAME}" ] && [ "${DB_NAME}" == "${INAME}" ] && ACTION=SIDB
[ "${DBSNAME}" == "${DB_NAME}" ] && [ ! "${DB_NAME}" == "${INAME}" ] && ACTION=RACDB
[ ! "${DBSNAME}" == "${DB_NAME}" ] && [ "${DB_NAME}" == "${INAME}" ] && ACTION=SIPDB && ORA_PDB_SID=${DBSNAME}
[ ! "${DBSNAME}" == "${DB_NAME}" ] && [ ! "${DB_NAME}" == "${INAME}" ] && ACTION=RACPDB && ORA_PDB_SID=${DBSNAME}
#echo "search DBname=${DBSNAME},db_name ${DB_NAME}, instance_name ${INAME}, actie ${ACTION}, ORA_PDB_SID ${ORA_PDB_SID} "
export ORACLE_SID=${DB_NAME}
INP=$(cat /etc/oratab | grep -v ^[0-9] | grep -v ^# | sed '/^\s*$/d'|grep ^${DB_NAME}:)
if [ -z "$INP" ]
then
echo "no entry found for ${DB} in /etc/oratab"
exit 1
else
OTE=$(echo ${INP}|cut -d':' -f1)
if [ "${OTE}" != "${DB_NAME}" ]
then echo "possible error for 2nd field (${DB_NAME}) in /etc/pdbtab"
exit 1
fi
fi
export ORAENV_ASK=NO
. oraenv > /dev/null 2>&1
export ORAENV_ASK=YES
case "${ACTION}" in
SIDB)
CON=Y
;;
SIPDB)
export ORACLE_PDB_SID=${DBSNAME}
checkPDB
;;
RACDB)
export ORACLE_SID=${INAME}
CON=Y
;;
RACPDB)
export ORACLE_SID=${INAME}
export ORACLE_PDB_SID=${DBSNAME}
checkPDB
;;
esac
[ "$CON" == "Y" ] && sqlplus / as sysdba
Als het script niet in het PATH staat kan er een symlink naar het script gemaakt worden in de $ORACLE_HOME/bin. In dit voorbeeld staat script sysdba in /beheer/oracle/bin/ .
[oracle@ageosn1 bin]$ cd $ORACLE_HOME/bin
[oracle@ageosn1 bin]$ ln -s /beheer/oracle/bin/sysdba sysdba
[oracle@ageosn1 bin]$
Voorbeeld van aanloggen als sysdba aan pdb:
[oracle@ab031 bin]$ sysdba D919NA
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Oct 4 12:33:20 2023
Version 19.16.0.0.0
Copyright (c) 1982, 2022, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.16.0.0.0
SQL> show con_name
CON_NAME
------------------------------
D919NA
SQL>
Voorbeeld van aanloggen aan niet bestaande pdb:
[oracle@ab031 bin]$ sysdba D919NC
no entry found for D919NC in /etc/pdbtab
[oracle@ab031 bin]$
Voorbeeld van aanloggen aan cdb$root:
[oracle@ab031 bin]$ sysdba CA919N2
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Oct 4 12:35:07 2023
Version 19.16.0.0.0
Copyright (c) 1982, 2022, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.16.0.0.0
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL>
Waar het voordat pdb's gebruik werden eenvoudig te achterhalen was welke oracle databases op een server aanwezig zijn door bijvoorbeeld een grep op het pmon proces, is dit voor pdbs's niet meer mogelijk
[oracle@ab031 bin]$ ps -ef|grep pmon|grep -v grep
oracle 9244 1 0 Aug09 ? 00:04:25 ora_pmon_CA919N2
[oracle@ab031 bin]$
Door het gebruik van /etc/pdbtab wordt het ook mogelijk om te checken welke pdb's op deze server zouden moeten draaien. Hiervoor is script showpdbs gemaakt.
[oracle@ab031 bin]$ showpdbs
D919P
D919NA
D919NB
D919NZ
[oracle@ab031 bin]$
Dit script controleert (nog) niet of de databases draaien maar kijkt alleen in /etc/pdbtab.
#!/bin/bash
# Het pad naar het bestand
bestand="/etc/pdbtab"
# Lees elke regel van het bestand
while IFS=: read -r veld1 veld2 veld3; do
# Controleer of de regel begint met "#"
if [[ ! "$veld1" =~ ^# ]]; then
# Controleer of veld1 verschilt van veld2
if [ "$veld1" != "$veld2" ]; then
# Toon de waarde van veld1 als het verschilt van veld2
echo "$veld1"
fi
fi
done < "$bestand"