Oracle

用於設置 Oracle Database Multitenant 環境的腳本

  • March 18, 2021

在使用安裝在不同家庭和不同版本中的多個 Oracle 容器數據庫的共享數據庫伺服器上工作時,可能很難快速找到所需的 pdb。我們使用了一個 shell 腳本來設置環境,我添加了一個 DB 查詢函式來顯示 PDBS。範例輸出:

Valid Oracle SIDs are:

               DBSXX1 SGA:  4900 MB  PGA:  1350 MB  DBROLE:  PRIMARY
               DBXXX2 SGA:  4900 MB  PGA:  1380 MB  DBROLE:  PHYSICAL STANDBY
               CDBXX001 [ PDB$SEED PDBXXX1 PDBXXX2 ...]  SGA:  64000 MB PGA:  16777 MB DBROLE:  PRIMARY
               CDBXX002 [ PDB$SEED PDBXXX1 PDBXXX2 ...]  SGA:  64000 MB PGA:  4443 MB DBROLE:  PRIMARY
               CDBXX003 [ PDB$SEED PDBXXX1 PDBXXX2 ...]  SGA:  32000 MB PGA:  11211 MB DBROLE:  PRIMARY
               CDBXX004 [ PDB$SEED PDBXXX1 PDBXXX2 ...]  SGA:  32000 MB PGA:  1111 MB DBROLE:  PRIMARY
               CDBXX005: Database offline
               ...
Enter the Oracle SID you require (default: CDBXX001):

Oracle SID is now CDBXX001, Oracle Home is /u01/app/oracle/product/19000/)

問題是腳本的性能。查詢導致延遲。是否有更好的解決方案來設置 oracle 多租戶的環境/顯示?改進構想?

完整腳本:

if [ -t 0 ]                             

function query_db() {
export ORACLE_SID=$1
export ORACLE_HOME=`grep "^${ORACLE_SID}:" /etc/oratab|cut -d: -f2 -s`
sqlplus -s / as sysdba<<SQL
set feedback off
set lines 1000
set pages 0
$2
SQL
}

then
       ORACLE_SID=""
       while [ -z "${ORACLE_SID}" ]
           do
                   tput clear; tput rev
                   echo "Valid Oracle SIDs are: "
                   tput rmso
                   for SID in `cat /etc/oratab|grep -v "^#"|cut -f1 -d: -s`
                   do
          if [[ $SID == `ps -ef | grep -w "ora_smon_$SID" | grep -v grep | cut -d _ -f3` ]]
then
                       CDB=$(query_db ${SID} "select cdb from v\$database;")
                       PDBS=$(query_db ${SID} "select name from v\$pdbs;")
                       #DBSIZE=$(query_db ${SID} "select sum (bytes) / 1024/1024/1024 AS SIZE from dba_data_files;")
                       SGA=$(query_db ${SID} "select trunc((sum(value)/1024/1024),-1) SGA from v\$sga;")
                       PGA=$(query_db ${SID} "select trunc((sum(pga_max_mem)/1024/1024),-1) PGA from v\$process;")
                       DBROLE=$(query_db ${SID} "select database_role from v\$database;")

                      if [[ "$CDB" == "YES" ]];
                       then
                        echo -e "\t\t${SID} "[" "${PDBS}" "]"  "SGA:" "${SGA} MB" "PGA:" "${PGA} MB" "DBROLE: " ${DBROLE}"
                        else
                        echo -e "\t\t${SID} "SGA:" "${SGA} MB"  "PGA:" "${PGA} MB"  "DBROLE: " ${DBROLE} "
                       fi
else
echo -e "\t\t${SID} : Database offline"
fi
           done
               DEFAULT=`cat /etc/oratab|grep -v "^#"|cut -d: -f1 -s|head -1`
               echo -e "\nEnter the Oracle SID you require (default: $DEFAULT): \c"
               read ANSWER
               [ "${ANSWER}" = "" ] && ANSWER=$DEFAULT
               export ORACLE_SID=`grep "^${ANSWER}:" /etc/oratab|cut -d: -f1 -s`
               export ORACLE_HOME=`grep "^${ANSWER}:" /etc/oratab|cut -d: -f2 -s`
               export AGENT_HOME="u01/app/oracle/product/emagent/agent_inst/"
               export OH=$ORACLE_HOME
               export DIAG="/u01/app/oracle/product/diag/rdbms/"${ORACLE_SID,,}"/"${ORACLE_SID^^}"/trace"
               export DIAGS="/u01/app/oracle/product/diag/rdbms/"${ORACLE_SID,,}s"/"${ORACLE_SID^^}"/trace"
               export TNS_ADMIN="/u01/app/oracle/product/network/admin"
               NEW_VER=`cat /etc/oratab | grep ^\`echo ${ORACLE_SID}:\` | cut -d'/' -f 5`
               export PATH=`echo $PATH | sed "s@/u01/app/oracle/[a-z]*/[0-9]*/[a-z0-9_]*@$ORACLE_HOME@g"`
               export LD_LIBRARY_PATH=`echo ${LD_LIBRARY_PATH} | sed "s@/u01/app/oracle/[a-z]*/[0-9]*/[a-z0-9_]*@$ORACLE_HOME@g"`
               if [ "${ORACLE_SID}" = "" ]
               then
                       echo -e "\n\n              ${ANSWER} : Invalid Oracle SID \c"
                       sleep 2
               fi
       done
else                                    # Set to first entry in oratab
       export ORACLE_SID=`cat /etc/oratab|grep -v "^#"|cut -d: -f1 -s|head -1`
       export ORACLE_HOME=`cat /etc/oratab|grep -v "^#"|cut -d: -f2 -s|head -1`
       export ORACLE_SID=`grep "^${ANSWER}:" /etc/oratab|cut -d: -f1 -s`
       export ORACLE_HOME=`grep "^${ANSWER}:" /etc/oratab|cut -d: -f2 -s`
       NEW_VER=`cat /etc/oratab | grep ^\`echo ${ORACLE_SID}:\` | cut -d'/' -f 5`
       export PATH=`echo ${PATH} | sed "s@/u01/app/oracle/[a-z]*/[0-9]*/[a-z0-9_]*@$ORACLE_HOME@g"`
       export LD_LIBRARY_PATH=`echo ${LD_LIBRARY_PATH} | sed "s@/u01/app/oracle/[a-z]*/[0-9]*/[a-z0-9_]*@$ORACLE_HOME@g"`
       export OH=$ORACLE_HOME
       export AGENT_HOME="/u01/app/oracle/product/emagent/agent_inst/"
       export DIAG="/u01/app/oracle/product/diag/rdbms/"${ORACLE_SID,,}"/"${ORACLE_SID^^}"/trace"
       export DIAGS="/u01/app/oracle/product/diag/rdbms/"${ORACLE_SID,,}s"/"${ORACLE_SID^^}"/trace"
       export TNS_ADMIN="/u01/app/oracle/product/network/admin"

fi
echo
echo Oracle SID is now `tput rev`$ORACLE_SID`tput rmso`, Oracle Home is `tput rev`$ORACLE_HOME`tput rmso`
echo

在我看來,您正在使這種方法變得比需要的更複雜並重新發明輪子(oraenv

這個怎麼樣?

#!/bin/sh
cat /etc/oratab |grep -v ^# | grep -v ^$
echo
echo Pick one of the above
source oraenv

我認為可用的 PDB 列表應該儲存在文件中而不是派生的,類似於可用數據庫列表儲存在 oratab 文件中的方式。儲存列表不僅速度更快,而且在 PDB 未向偵聽器註冊(例如已關閉)的情況下也更可靠。這類似於從 oratab 獲取 SID 列表比從“ps -ef | grep pmon”動態建構 SID 列表更可靠(如果關閉 db 怎麼辦?)。

由於 Oracle 沒有 PDB 列表文件,因此在我的環境中,我維護自己的文件,其中包含兩個欄位:

cat cdb_pdb_list
cdb1 pdb11
cdb1 pdb12
...

然後設置 PDB 環境,我使用數據庫選擇器腳本,它允許我從 oratab 的 SID 組合列表和 pdb 列表文件的 PID 組合列表中進行選擇。選擇後,腳本設置 ORACLE_SID 和 ORACLE_PDB_SID 變數,然後為其他變數呼叫標準“oraenv”。與“sqlplus / as sysdba”等的任何後續本地連接都將轉到選定的 PDB。

使用範例: 注意 PDB 如何在列表中顯示為“cdb:pdb”


hostname:+ASM::/home/oracle:> . sid

Select your database:

1) -MGMTDB                       10) db2                     19) db11
2) +ASM                          11) db3                     20) db12
3) cdb1                          12) db4                     21) db13
4) cdb1:pdb11                    13) db5                     22) db14
5) cdb1:pdb12                    14) db6                     23) db15
6) cdb1:pdb13                    15) db7                     24) db16
7) cdb2                          16) db8                     25) db17
8) cdb2:pdb21                    17) db9                     26) db18
9) cdb2:pdb_dropme               18) db10                    27) db19
Your choice (enter number)? 5
Selected database: cdb1:pdb12
ORACLE_SID: cdb11
ORACLE_PDB_SID: pdb12
The Oracle base remains unchanged with value /u01/app/oracle

hostname:cdb11:pdb12:/home/oracle:>
hostname:cdb11:pdb12:/home/oracle:> sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Thu Mar 18 12:27:10 2021
Version 19.10.0.0.0

Copyright (c) 1982, 2020, Oracle.  All rights reserved.

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.10.0.0.0

SQL> show con_name
CON_NAME
------------------------------
PDB12

SQL>

這是數據庫選擇器腳本。用“dot”或“source”呼叫它以將變數持久保存在父 shell 中。

#!/usr/bin/ksh
# July 2019 Albert Balbekov
#
# Interactive database picker
# Displays menu of databases defined in oratab then asks which one to use then uses oraenv to set env variables
#
# This script is normally sourced in user shell to be able to change parent shell variables
# alias sid='source $HOME/admin/script/sid'
#
# History:
#       July 2019       Initial creation
#       Mar 2021        Adding PDBs
#

CDB_PDB_LIST=/home/oracle/admin/scripts/cdb_pdb_list

# check if we are on grid
GRID_HOME=$( grep '^\+ASM' /var/opt/oracle/oratab | cut -f 2 -d: )

# get list of instances from oratab
if [ ! -z "${GRID_HOME}" ]; then
   # remove trailing digit since we are on RAC
   # then sort and uniq to remove duplicates
   # this gives list of databases (as opposite to list of instances)
   DBS="$( grep -v '^#' /var/opt/oracle/oratab | cut -f 1 -d: | sed 's/[0-9]$//' | sort | uniq )"
else
   DBS="$( grep -v '^#' /var/opt/oracle/oratab | cut -f 1 -d: | sort )"
fi

# get list of PDBs from cdb_pdb_list
PDBS="$( cat $CDB_PDB_LIST | awk '{print $1 ":" $2}' )"

# combine and sort
DBS="$( printf '%s\n' $DBS $PDBS | sort )"

echo "\n"
echo 'Select your database:'
echo "\n"

PS3="Your choice (enter number)? "

# if user is in ksh then select menu tends to use all vertical space before wrapping menu to another column
# we will limit terminal rows with stty to force select to wrap menu earlier
#saverows=$( stty | grep rows | cut -f1 -d";" | cut -f2 -d"=" )
stty rows 7

select db in $DBS; do
   if [[ -n $db ]]; then
      echo "Selected database: "$db
      # can place db-specific actions here ...
      break
   else
      echo "Invalid."
   fi
done

# reset stty size back to what it was
#stty rows $saverows
resize > /dev/null

pid="$( echo $db: | cut -d: -f2 )"
db="$( echo $db: | cut -d: -f1 )"

# construct ORACLE_SID by adding RAC node number to db name
if [[ -n "${GRID_HOME}" ]]; then
   # determine RAC node number
   RAC_NODE_NUM=$( $GRID_HOME/bin/olsnodes -n | grep `hostname` | cut -f2 )

   # add RAC node number to database name to get SID
   export ORACLE_SID=${db}${RAC_NODE_NUM}
else
  # not a RAC - SID is db
  export ORACLE_SID=$db
fi
export ORACLE_UNQNAME=${db}
export ORACLE_PDB_SID=$pid

echo ORACLE_SID: $ORACLE_SID
echo ORACLE_PDB_SID: $ORACLE_PDB_SID

SAVE_ORAENV_ASK=$ORAENV_ASK
ORAENV_ASK=NO
source oraenv
ORAENV_ASK=$SAVE_ORAENV_ASK

引用自:https://dba.stackexchange.com/questions/281795