GitHub Copilot
Your script does a good job of estimating SGA requirements based on the init.ora
file. However, to fully reproduce and diagnose SGA/ORA-00821/ORA-00838 issues in real-world Oracle environments, you should also consider the following OS and system-level factors:
1. HugePages Configuration
- If HugePages are not configured or are insufficient, Oracle may fail to allocate large SGA values, even if enough RAM is available.
- Check HugePages status:
- Check Oracle's HugePages recommendations:
- Oracle script for HugePages:
2. OS Memory Limits
- ulimit settings for the Oracle user can restrict memory allocation.
- /etc/security/limits.conf should have appropriate values for
memlock
, nofile
, etc.
3. Transparent HugePages (THP)
- THP should be disabled for Oracle databases.
4. Kernel Shared Memory Parameters
- Check and tune
shmmax
, shmall
, etc., in /etc/sysctl.conf
:
5. NUMA Settings
- On systems with Non-Uniform Memory Access (NUMA), improper configuration can affect SGA allocation.
6. Swap Space
- Ensure swap is not overused, and enough physical RAM is available.
7. Oracle Version/Platform Bugs
- Some Oracle versions/platforms have bugs or quirks with certain SGA sizes or OS configurations. Always check Oracle support notes for your version.
Summary Table for Reproduction Checklist
Factor How to Check/Test Why Important HugePages /proc/meminfo
, Oracle scriptsSGA allocation efficiency ulimit/limits.conf ulimit -a
, /etc/security/limits.conf
Process memory limits Transparent HugePages /sys/kernel/mm/transparent_hugepage/enabled
Should be disabled Kernel shm params `sysctl -a grep shm` NUMA numactl --hardware
Memory locality/performance Swap free -m
Avoid swapping SGA
Recommendation
- Include these OS-level checks in your test script or documentation.
- Document the OS/kernel settings and their values when reproducing or troubleshooting SGA-related startup issues.
- If possible, automate the collection of these values for easier diagnosis.
Including these OS and kernel settings will make your SGA/ORA-00821/ORA-00838 reproduction and troubleshooting much more robust and reliable.
#!/bin/bash#!/bin/bash
#!/bin/bash
# --- Configuration ---LOG_FILE="noncdb_to_pdb_conversion.log"PROMPT_USER=trueSCRIPT_STATE_FILE="conversion_state.txt"TOTAL_TIME=0ALERT_LOG_DIR="/path/to/alert/logs" # Update this path to your alert log directory
# --- Function Definitions ---
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"}
prompt_user() { if [[ "$PROMPT_USER" == "true" ]]; then local response while true; do read -p "$1 (yes/no): " response case "$response" in [yY][eE][sS]) log "User confirmed: $1"; return 0 ;; [nN][oO]) log "User rejected: $1"; log "Exiting script."; exit 1 ;; *) echo "Invalid input. Please enter 'yes' or 'no'." ;; esac done else log "Automatic: $1" return 0 fi}
get_current_state() { [[ -f "$SCRIPT_STATE_FILE" ]] && cat "$SCRIPT_STATE_FILE" || echo "START"}
set_current_state() { echo "$1" > "$SCRIPT_STATE_FILE"}
get_sids_from_pmon() { ps -ef | grep pmon | grep -v grep | grep -iv asm | grep -iv apx | awk '{print $8}' | awk -F "_" '{print $3}'}
choose_sid() { local options=("$@") local num_options=${#options[@]} if (( num_options == 0 )); then log "No SIDs provided to choose from." exit 1 fi echo "Please choose a SID:" for ((i=0; i<num_options; i++)); do echo "$((i+1))) ${options[$i]}" done while true; do read -p "Enter your choice (1-$num_options): " choice if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= num_options )); then echo "${options[$((choice-1))]}" return 0 else echo "Invalid choice. Please enter a number between 1 and $num_options." fi done}
is_cdb() { local sid="$1" export ORACLE_SID="$sid" local result=$(sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select cdb from v\\$database; exitEOF ) [[ "$result" == "YES" ]]}
get_datafile_path() { local sid="$1" export ORACLE_SID="$sid" sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select name from v\\$datafile where rownum=1; exitEOF}
execute_sql_command() { local sql_command="$1" local sid="$2" export ORACLE_SID="$sid" local start_time=$(date +%s) log "Executing SQL command: $sql_command for database: $sid" sqlplus -s "/ as sysdba" <<-EOF WHENEVER SQLERROR EXIT FAILURE; $sql_command; exit;EOF local status=$? local end_time=$(date +%s) local duration=$((end_time - start_time)) if [[ "$status" -eq 0 ]]; then log "SQL command for $sid succeeded." else log "SQL command for $sid failed." check_alert_log "$sid" exit 1 fi if (( duration > 60 )); then log "SQL command took $((duration / 60)) minutes and $((duration % 60)) seconds to complete." else log "SQL command took $duration seconds to complete." fi ((TOTAL_TIME+=duration))}
check_alert_log() { local sid="$1" local alert_log_file="$ALERT_LOG_DIR/alert_$sid.log" if [[ -f "$alert_log_file" ]]; then log "Checking alert log for $sid: $alert_log_file" grep -i "error" "$alert_log_file" | tail -n 10 | tee -a "$LOG_FILE" else log "Alert log file not found for $sid." fi}
time_step() { local step_name="$1" local -n step_code_ref="$2" local start_time=$(date +%s) log "Starting step: $step_name" "${step_code_ref[@]}" local end_time=$(date +%s) local duration=$((end_time - start_time)) if (( duration > 60 )); then log "Step '$step_name' took $((duration / 60)) minutes and $((duration % 60)) seconds to complete." else log "Step '$step_name' took $duration seconds to complete." fi ((TOTAL_TIME+=duration))}
# --- Script Start ---
> "$LOG_FILE"log "Script started."CURRENT_STATE=$(get_current_state)log "Current state: $CURRENT_STATE"
# --- Step 1: Find PMON processes and select SIDs ---step1_code=( prompt_user "Proceed with finding PMON processes and selecting SIDs?" if command -v mapfile &> /dev/null; then mapfile -t SIDS < <(get_sids_from_pmon) else IFS=$'\n' read -d '' -r -a SIDS < <(get_sids_from_pmon) fi PMON_COUNT=${#SIDS[@]} log "Found $PMON_COUNT PMON processes: ${SIDS[*]}" if (( PMON_COUNT < 2 )); then log "Error: Less than 2 PMON processes found. Need a non-CDB and a CDB running." exit 1 fi # Prompt user to select SIDs echo "Available Oracle SIDs:" for i in "${!SIDS[@]}"; do echo "$((i+1))) ${SIDS[$i]}" done read -p "Enter the number for the CDB SID (or press Enter to auto-select): " cdb_choice read -p "Enter the number for the NONCDB SID (or press Enter to auto-select): " noncdb_choice if [[ "$cdb_choice" =~ ^[0-9]+$ ]] && (( cdb_choice >= 1 && cdb_choice <= PMON_COUNT )); then CDB_SID="${SIDS[$((cdb_choice-1))]}" fi if [[ "$noncdb_choice" =~ ^[0-9]+$ ]] && (( noncdb_choice >= 1 && noncdb_choice <= PMON_COUNT )); then NONCDB_SID="${SIDS[$((noncdb_choice-1))]}" fi # If user didn't select, auto-detect if [[ -z "$CDB_SID" || -z "$NONCDB_SID" || "$CDB_SID" == "$NONCDB_SID" ]]; then log "Auto-selecting CDB and NONCDB SIDs..." for sid in "${SIDS[@]}"; do if is_cdb "$sid"; then CDB_SID="$sid" else NONCDB_SID="$sid" fi done fi # Final validation if [[ -z "$CDB_SID" || -z "$NONCDB_SID" || "$CDB_SID" == "$NONCDB_SID" ]]; then log "Error: Could not determine valid CDB and NONCDB SIDs." exit 1 fi log "Selected CDB_SID: $CDB_SID" log "Selected NONCDB_SID: $NONCDB_SID" set_current_state "SIDS_SELECTED" CURRENT_STATE="SIDS_SELECTED")
if [[ "$CURRENT_STATE" == "START" ]]; then time_step "Step 1: Finding PMON processes and selecting SIDs." step1_codefi
# --- Step 2: Check CDB vs Non-CDB ---step2_code=( log "Step 2: Checking CDB vs. Non-CDB." prompt_user "Proceed with checking CDB vs. Non-CDB?" if ! is_cdb "$CDB_SID"; then log "Error: $CDB_SID is not a CDB." exit 1 fi if is_cdb "$NONCDB_SID"; then log "Error: $NONCDB_SID is a CDB." exit 1 fi log "CDB_SID: $CDB_SID" log "NONCDB_SID: $NONCDB_SID" set_current_state "DB_TYPES_CHECKED" CURRENT_STATE="DB_TYPES_CHECKED")
if [[ "$CURRENT_STATE" == "SIDS_SELECTED" ]]; then time_step "Step 2: Checking CDB vs. Non-CDB." step2_codefi
# --- Step 3: Get Datafile Paths ---step3_code=( log "Step 3: Getting Datafile Paths." prompt_user "Proceed with getting datafile paths?" NONCDB_DATAFILE_PATH=$(get_datafile_path "$NONCDB_SID") if [[ -z "$NONCDB_DATAFILE_PATH" ]]; then log "Error getting non-CDB datafile path" exit 1 fi log "Non-CDB datafile path: $NONCDB_DATAFILE_PATH" CDB_DATAFILE_PATH=$(get_datafile_path "$CDB_SID") if [[ -z "$CDB_DATAFILE_PATH" ]]; then log "Error getting CDB datafile path" exit 1 fi log "CDB datafile path: $CDB_DATAFILE_PATH" NONCDB_DIR=$(dirname "$NONCDB_DATAFILE_PATH") CDB_DIR=$(dirname "$CDB_DATAFILE_PATH") log "Non-CDB directory: $NONCDB_DIR" log "CDB directory: $CDB_DIR" set_current_state "DATAFILE_PATHS_RETRIEVED" CURRENT_STATE="DATAFILE_PATHS_RETRIEVED")
if [[ "$CURRENT_STATE" == "DB_TYPES_CHECKED" ]]; then time_step "Step 3: Getting Datafile Paths." step3_codefi
# --- Step 4: Non CDB Preparation ---step4_code=( log "Step 4: Non-CDB Preparation." prompt_user "Proceed with non-CDB preparation?" execute_sql_command "alter database open read only" "$NONCDB_SID" # Validate open mode mode=$(sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select open_mode from v\\$database; exitEOF ) if [[ "$mode" != *"READ ONLY"* ]]; then log "Error: Non-CDB is not in READ ONLY mode after command. Current mode: $mode" exit 1 fi execute_sql_command "exec dbms_pdb.describe(pdb_descr_file=>'/tmp/new_pdb.xml');" "$NONCDB_SID" execute_sql_command "shutdown immediate;" "$NONCDB_SID" set_current_state "NONCDB_PREPARED" CURRENT_STATE="NONCDB_PREPARED")
if [[ "$CURRENT_STATE" == "DATAFILE_PATHS_RETRIEVED" ]]; then time_step "Step 4: Non-CDB Preparation." step4_codefi
# --- Step 5: Create PDB ---step5_code=( log "Step 5: Create PDB." prompt_user "Proceed with PDB creation?" PDB_NAME=PDBNEW NEW_LOCATION="$CDB_DIR/$PDB_NAME" # Prompt for method echo "Choose the method for PDB creation:" echo "1. nocopy (default)" echo "2. copy" echo "3. move" read -p "Enter your choice (1-3, default 1): " method_choice case "$method_choice" in 2) METHOD="copy" ;; 3) METHOD="move" ;; *) METHOD="nocopy" ;; esac case "$METHOD" in nocopy) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' NOCOPY;" "$CDB_SID" ;; copy) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' COPY file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID" ;; move) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' MOVE file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID" ;; esac set_current_state "PDB_CREATED" CURRENT_STATE="PDB_CREATED")
if [[ "$CURRENT_STATE" == "NONCDB_PREPARED" ]]; then time_step "Step 5: Create PDB." step5_codefi
# --- Step 6: Post conversion process ---step6_code=( log "Step 6: Post PDB creation process" prompt_user "Proceed with post PDB creation process?" execute_sql_command "alter pluggable database $PDB_NAME open read write;" "$CDB_SID" execute_sql_command "@\$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql;" "$PDB_NAME" set_current_state "COMPLETE" CURRENT_STATE="COMPLETE")
if [[ "$CURRENT_STATE" == "PDB_CREATED" ]]; then time_step "Step 6: Post PDB creation process" step6_codefi
# --- Finalization ---if [[ "$CURRENT_STATE" == "COMPLETE" ]]; then log "Conversion completed successfully." log "You should verify that everything is working properly." rm -f "$SCRIPT_STATE_FILE"else log "Conversion failed or was interrupted at state: $CURRENT_STATE" log "You can restart the script to continue."fi
if (( TOTAL_TIME > 60 )); then log "Total time for the entire procedure: $((TOTAL_TIME / 60)) minutes and $((TOTAL_TIME % 60)) seconds"else log "Total time for the entire procedure: $TOTAL_TIME seconds"fi
log "Script finished."exit 0
===test mode
#!/bin/bash
# --- Configuration ---LOG_FILE="noncdb_to_pdb_conversion.log"PROMPT_USER=trueSCRIPT_STATE_FILE="conversion_state.txt"TOTAL_TIME=0ALERT_LOG_DIR="/path/to/alert/logs" # Update this path to your alert log directoryTEST_MODE=true # Set to true for testing mode, false for actual execution
# --- Function Definitions ---
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"}
prompt_user() { if [[ "$PROMPT_USER" == "true" ]]; then local response while true; do read -p "$1 (yes/no): " response case "$response" in [yY][eE][sS]) log "User confirmed: $1"; return 0 ;; [nN][oO]) log "User rejected: $1"; log "Exiting script."; exit 1 ;; *) echo "Invalid input. Please enter 'yes' or 'no'." ;; esac done else log "Automatic: $1" return 0 fi}
get_current_state() { [[ -f "$SCRIPT_STATE_FILE" ]] && cat "$SCRIPT_STATE_FILE" || echo "START"}
set_current_state() { echo "$1" > "$SCRIPT_STATE_FILE"}
get_sids_from_pmon() { ps -ef | grep pmon | grep -v grep | grep -iv asm | grep -iv apx | awk '{print $8}' | awk -F "_" '{print $3}'}
choose_sid() { local options=("$@") local num_options=${#options[@]} if (( num_options == 0 )); then log "No SIDs provided to choose from." exit 1 fi echo "Please choose a SID:" for ((i=0; i<num_options; i++)); do echo "$((i+1))) ${options[$i]}" done while true; do read -p "Enter your choice (1-$num_options): " choice if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= num_options )); then echo "${options[$((choice-1))]}" return 0 else echo "Invalid choice. Please enter a number between 1 and $num_options." fi done}
is_cdb() { local sid="$1" export ORACLE_SID="$sid" local result=$(sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select cdb from v\\$database; exitEOF ) [[ "$result" == "YES" ]]}
get_datafile_path() { local sid="$1" export ORACLE_SID="$sid" sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select name from v\\$datafile where rownum=1; exitEOF}
execute_sql_command() { local sql_command="$1" local sid="$2" export ORACLE_SID="$sid" if [[ "$TEST_MODE" == "true" ]]; then log "TEST MODE: Would execute SQL command: $sql_command for database: $sid" return 0 fi local start_time=$(date +%s) log "Executing SQL command: $sql_command for database: $sid" sqlplus -s "/ as sysdba" <<-EOF WHENEVER SQLERROR EXIT FAILURE; $sql_command; exit;EOF local status=$? local end_time=$(date +%s) local duration=$((end_time - start_time)) if [[ "$status" -eq 0 ]]; then log "SQL command for $sid succeeded." else log "SQL command for $sid failed." check_alert_log "$sid" exit 1 fi if (( duration > 60 )); then log "SQL command took $((duration / 60)) minutes and $((duration % 60)) seconds to complete." else log "SQL command took $duration seconds to complete." fi ((TOTAL_TIME+=duration))}
check_alert_log() { local sid="$1" local alert_log_file="$ALERT_LOG_DIR/alert_$sid.log" if [[ -f "$alert_log_file" ]]; then log "Checking alert log for $sid: $alert_log_file" grep -i "error" "$alert_log_file" | tail -n 10 | tee -a "$LOG_FILE" else log "Alert log file not found for $sid." fi}
time_step() { local step_name="$1" local -n step_code_ref="$2" local start_time=$(date +%s) log "Starting step: $step_name" "${step_code_ref[@]}" local end_time=$(date +%s) local duration=$((end_time - start_time)) if (( duration > 60 )); then log "Step '$step_name' took $((duration / 60)) minutes and $((duration % 60)) seconds to complete." else log "Step '$step_name' took $duration seconds to complete." fi ((TOTAL_TIME+=duration))}
# --- Script Start ---
> "$LOG_FILE"log "Script started."CURRENT_STATE=$(get_current_state)log "Current state: $CURRENT_STATE"
# --- Step 1: Find PMON processes and select SIDs ---step1_code=( prompt_user "Proceed with finding PMON processes and selecting SIDs?" if command -v mapfile &> /dev/null; then mapfile -t SIDS < <(get_sids_from_pmon) else IFS=$'\n' read -d '' -r -a SIDS < <(get_sids_from_pmon) fi PMON_COUNT=${#SIDS[@]} log "Found $PMON_COUNT PMON processes: ${SIDS[*]}" if (( PMON_COUNT < 2 )); then log "Error: Less than 2 PMON processes found. Need a non-CDB and a CDB running." exit 1 fi # Prompt user to select SIDs echo "Available Oracle SIDs:" for i in "${!SIDS[@]}"; do echo "$((i+1))) ${SIDS[$i]}" done read -p "Enter the number for the CDB SID (or press Enter to auto-select): " cdb_choice read -p "Enter the number for the NONCDB SID (or press Enter to auto-select): " noncdb_choice if [[ "$cdb_choice" =~ ^[0-9]+$ ]] && (( cdb_choice >= 1 && cdb_choice <= PMON_COUNT )); then CDB_SID="${SIDS[$((cdb_choice-1))]}" fi if [[ "$noncdb_choice" =~ ^[0-9]+$ ]] && (( noncdb_choice >= 1 && noncdb_choice <= PMON_COUNT )); then NONCDB_SID="${SIDS[$((noncdb_choice-1))]}" fi # If user didn't select, auto-detect if [[ -z "$CDB_SID" || -z "$NONCDB_SID" || "$CDB_SID" == "$NONCDB_SID" ]]; then log "Auto-selecting CDB and NONCDB SIDs..." for sid in "${SIDS[@]}"; do if is_cdb "$sid"; then CDB_SID="$sid" else NONCDB_SID="$sid" fi done fi # Final validation if [[ -z "$CDB_SID" || -z "$NONCDB_SID" || "$CDB_SID" == "$NONCDB_SID" ]]; then log "Error: Could not determine valid CDB and NONCDB SIDs." exit 1 fi log "Selected CDB_SID: $CDB_SID" log "Selected NONCDB_SID: $NONCDB_SID" set_current_state "SIDS_SELECTED" CURRENT_STATE="SIDS_SELECTED")
if [[ "$CURRENT_STATE" == "START" ]]; then time_step "Step 1: Finding PMON processes and selecting SIDs." step1_codefi
# --- Step 2: Check CDB vs Non-CDB ---step2_code=( log "Step 2: Checking CDB vs. Non-CDB." prompt_user "Proceed with checking CDB vs. Non-CDB?" if ! is_cdb "$CDB_SID"; then log "Error: $CDB_SID is not a CDB." exit 1 fi if is_cdb "$NONCDB_SID"; then log "Error: $NONCDB_SID is a CDB." exit 1 fi log "CDB_SID: $CDB_SID" log "NONCDB_SID: $NONCDB_SID" set_current_state "DB_TYPES_CHECKED" CURRENT_STATE="DB_TYPES_CHECKED")
if [[ "$CURRENT_STATE" == "SIDS_SELECTED" ]]; then time_step "Step 2: Checking CDB vs. Non-CDB." step2_codefi
# --- Step 3: Get Datafile Paths ---step3_code=( log "Step 3: Getting Datafile Paths." prompt_user "Proceed with getting datafile paths?" NONCDB_DATAFILE_PATH=$(get_datafile_path "$NONCDB_SID") if [[ -z "$NONCDB_DATAFILE_PATH" ]]; then log "Error getting non-CDB datafile path" exit 1 fi log "Non-CDB datafile path: $NONCDB_DATAFILE_PATH" CDB_DATAFILE_PATH=$(get_datafile_path "$CDB_SID") if [[ -z "$CDB_DATAFILE_PATH" ]]; then log "Error getting CDB datafile path" exit 1 fi log "CDB datafile path: $CDB_DATAFILE_PATH" NONCDB_DIR=$(dirname "$NONCDB_DATAFILE_PATH") CDB_DIR=$(dirname "$CDB_DATAFILE_PATH") log "Non-CDB directory: $NONCDB_DIR" log "CDB directory: $CDB_DIR" set_current_state "DATAFILE_PATHS_RETRIEVED" CURRENT_STATE="DATAFILE_PATHS_RETRIEVED")
if [[ "$CURRENT_STATE" == "DB_TYPES_CHECKED" ]]; then time_step "Step 3: Getting Datafile Paths." step3_codefi
# --- Step 4: Non CDB Preparation ---step4_code=( log "Step 4: Non-CDB Preparation." prompt_user "Proceed with non-CDB preparation?" if [[ "$TEST_MODE" == "true" ]]; then log "TEST MODE: Would execute 'alter database open read only' for $NONCDB_SID" log "TEST MODE: Would execute 'exec dbms_pdb.describe(pdb_descr_file=>'/tmp/new_pdb.xml');' for $NONCDB_SID" log "TEST MODE: Would execute 'shutdown immediate;' for $NONCDB_SID" else execute_sql_command "alter database open read only" "$NONCDB_SID" # Validate open mode mode=$(sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select open_mode from v\\$database; exitEOF ) if [[ "$mode" != *"READ ONLY"* ]]; then log "Error: Non-CDB is not in READ ONLY mode after command. Current mode: $mode" exit 1 fi execute_sql_command "exec dbms_pdb.describe(pdb_descr_file=>'/tmp/new_pdb.xml');" "$NONCDB_SID" execute_sql_command "shutdown immediate;" "$NONCDB_SID" fi set_current_state "NONCDB_PREPARED" CURRENT_STATE="NONCDB_PREPARED")
if [[ "$CURRENT_STATE" == "DATAFILE_PATHS_RETRIEVED" ]]; then time_step "Step 4: Non-CDB Preparation." step4_codefi
# --- Step 5: Create PDB ---step5_code=( log "Step 5: Create PDB." prompt_user "Proceed with PDB creation?" PDB_NAME=PDBNEW NEW_LOCATION="$CDB_DIR/$PDB_NAME" # Prompt for method echo "Choose the method for PDB creation:" echo "1. nocopy (default)" echo "2. copy" echo "3. move" read -p "Enter your choice (1-3, default 1): " method_choice case "$method_choice" in 2) METHOD="copy" ;; 3) METHOD="move" ;; *) METHOD="nocopy" ;; esac if [[ "$TEST_MODE" == "true" ]]; then log "TEST MODE: Would execute PDB creation with method $METHOD for $CDB_SID" else case "$METHOD" in nocopy) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' NOCOPY;" "$CDB_SID" ;; copy) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' COPY file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID" ;; move) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' MOVE file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID" ;; esac fi set_current_state "PDB_CREATED" CURRENT_STATE="PDB_CREATED")
if [[ "$CURRENT_STATE" == "NONCDB_PREPARED" ]]; then time_step "Step 5: Create PDB." step5_codefi
# --- Step 6: Post conversion process ---step6_code=( log "Step 6: Post PDB creation process" prompt_user "Proceed with post PDB creation process?" if [[ "$TEST_MODE" == "true" ]]; then log "TEST MODE: Would execute 'alter pluggable database $PDB_NAME open read write;' for $CDB_SID" log "TEST MODE: Would execute '@\$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql;' for $PDB_NAME" else execute_sql_command "alter pluggable database $PDB_NAME open read write;" "$CDB_SID" execute_sql_command "@\$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql;" "$PDB_NAME" fi set_current_state "COMPLETE" CURRENT_STATE="COMPLETE")
if [[ "$CURRENT_STATE" == "PDB_CREATED" ]]; then time_step "Step 6: Post PDB creation process" step6_codefi
# --- Finalization ---if [[ "$CURRENT_STATE" == "COMPLETE" ]]; then log "Conversion completed successfully." log "You should verify that everything is working properly." rm -f "$SCRIPT_STATE_FILE"else log "Conversion failed or was interrupted at state: $CURRENT_STATE" log "You can restart the script to continue."fi
if (( TOTAL_TIME > 60 )); then log "Total time for the entire procedure: $((TOTAL_TIME / 60)) minutes and $((TOTAL_TIME % 60)) seconds"else log "Total time for the entire procedure: $TOTAL_TIME seconds"fi
log "Script finished."exit 0
==nomore
#!/bin/bash
# --- Configuration ---LOG_FILE="noncdb_to_pdb_conversion.log"PROMPT_USER=trueSCRIPT_STATE_FILE="conversion_state.txt"TOTAL_TIME=0
# --- Function Definitions ---
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"}
prompt_user() { if [[ "$PROMPT_USER" == "true" ]]; then local response while true; do read -p "$1 (yes/no): " response case "$response" in [yY][eE][sS]) log "User confirmed: $1"; return 0 ;; [nN][oO]) log "User rejected: $1"; log "Exiting script."; exit 1 ;; *) echo "Invalid input. Please enter 'yes' or 'no'." ;; esac done else log "Automatic: $1" return 0 fi}
get_current_state() { [[ -f "$SCRIPT_STATE_FILE" ]] && cat "$SCRIPT_STATE_FILE" || echo "START"}
set_current_state() { echo "$1" > "$SCRIPT_STATE_FILE"}
get_sids_from_pmon() { ps -ef | grep pmon | grep -v grep | grep -iv asm | grep -iv apx | awk '{print $8}' | awk -F "_" '{print $3}'}
choose_sid() { local options=("$@") local num_options=${#options[@]} if (( num_options == 0 )); then log "No SIDs provided to choose from." exit 1 fi echo "Please choose a SID:" for ((i=0; i<num_options; i++)); do echo "$((i+1))) ${options[$i]}" done while true; do read -p "Enter your choice (1-$num_options): " choice if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= num_options )); then echo "${options[$((choice-1))]}" return 0 else echo "Invalid choice. Please enter a number between 1 and $num_options." fi done}
is_cdb() { local sid="$1" export ORACLE_SID="$sid" local result=$(sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select cdb from v\\$database; exitEOF ) [[ "$result" == "YES" ]]}
get_datafile_path() { local sid="$1" export ORACLE_SID="$sid" sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select name from v\\$datafile where rownum=1; exitEOF}
execute_sql_command() { local sql_command="$1" local sid="$2" export ORACLE_SID="$sid" local start_time=$(date +%s) log "Executing SQL command: $sql_command for database: $sid" sqlplus -s "/ as sysdba" <<-EOF WHENEVER SQLERROR EXIT FAILURE; $sql_command; exit;EOF local status=$? local end_time=$(date +%s) local duration=$((end_time - start_time)) if [[ "$status" -eq 0 ]]; then log "SQL command for $sid succeeded." else log "SQL command for $sid failed." exit 1 fi if (( duration > 60 )); then log "SQL command took $((duration / 60)) minutes and $((duration % 60)) seconds to complete." else log "SQL command took $duration seconds to complete." fi ((TOTAL_TIME+=duration))}
time_step() { local step_name="$1" local -n step_code_ref="$2" local start_time=$(date +%s) log "Starting step: $step_name" "${step_code_ref[@]}" local end_time=$(date +%s) local duration=$((end_time - start_time)) if (( duration > 60 )); then log "Step '$step_name' took $((duration / 60)) minutes and $((duration % 60)) seconds to complete." else log "Step '$step_name' took $duration seconds to complete." fi ((TOTAL_TIME+=duration))}
# --- Script Start ---
> "$LOG_FILE"log "Script started."CURRENT_STATE=$(get_current_state)log "Current state: $CURRENT_STATE"
# --- Step 1: Find PMON processes and select SIDs ---step1_code=( prompt_user "Proceed with finding PMON processes and selecting SIDs?" mapfile -t SIDS < <(get_sids_from_pmon) PMON_COUNT=${#SIDS[@]} log "Found $PMON_COUNT PMON processes: ${SIDS[*]}" if (( PMON_COUNT < 2 )); then log "Error: Less than 2 PMON processes found. Need a non-CDB and a CDB running." exit 1 fi # Prompt user to select SIDs echo "Available Oracle SIDs:" for i in "${!SIDS[@]}"; do echo "$((i+1))) ${SIDS[$i]}" done read -p "Enter the number for the CDB SID (or press Enter to auto-select): " cdb_choice read -p "Enter the number for the NONCDB SID (or press Enter to auto-select): " noncdb_choice if [[ "$cdb_choice" =~ ^[0-9]+$ ]] && (( cdb_choice >= 1 && cdb_choice <= PMON_COUNT )); then CDB_SID="${SIDS[$((cdb_choice-1))]}" fi if [[ "$noncdb_choice" =~ ^[0-9]+$ ]] && (( noncdb_choice >= 1 && noncdb_choice <= PMON_COUNT )); then NONCDB_SID="${SIDS[$((noncdb_choice-1))]}" fi # If user didn't select, auto-detect if [[ -z "$CDB_SID" || -z "$NONCDB_SID" || "$CDB_SID" == "$NONCDB_SID" ]]; then log "Auto-selecting CDB and NONCDB SIDs..." for sid in "${SIDS[@]}"; do if is_cdb "$sid"; then CDB_SID="$sid" else NONCDB_SID="$sid" fi done fi # Final validation if [[ -z "$CDB_SID" || -z "$NONCDB_SID" || "$CDB_SID" == "$NONCDB_SID" ]]; then log "Error: Could not determine valid CDB and NONCDB SIDs." exit 1 fi log "Selected CDB_SID: $CDB_SID" log "Selected NONCDB_SID: $NONCDB_SID" set_current_state "SIDS_SELECTED" CURRENT_STATE="SIDS_SELECTED")
if [[ "$CURRENT_STATE" == "START" ]]; then time_step "Step 1: Finding PMON processes and selecting SIDs." step1_codefi
# --- Step 2: Check CDB vs Non-CDB ---step2_code=( log "Step 2: Checking CDB vs. Non-CDB." prompt_user "Proceed with checking CDB vs. Non-CDB?" if ! is_cdb "$CDB_SID"; then log "Error: $CDB_SID is not a CDB." exit 1 fi if is_cdb "$NONCDB_SID"; then log "Error: $NONCDB_SID is a CDB." exit 1 fi log "CDB_SID: $CDB_SID" log "NONCDB_SID: $NONCDB_SID" set_current_state "DB_TYPES_CHECKED" CURRENT_STATE="DB_TYPES_CHECKED")
if [[ "$CURRENT_STATE" == "SIDS_SELECTED" ]]; then time_step "Step 2: Checking CDB vs. Non-CDB." step2_codefi
# --- Step 3: Get Datafile Paths ---step3_code=( log "Step 3: Getting Datafile Paths." prompt_user "Proceed with getting datafile paths?" NONCDB_DATAFILE_PATH=$(get_datafile_path "$NONCDB_SID") if [[ -z "$NONCDB_DATAFILE_PATH" ]]; then log "Error getting non-CDB datafile path" exit 1 fi log "Non-CDB datafile path: $NONCDB_DATAFILE_PATH" CDB_DATAFILE_PATH=$(get_datafile_path "$CDB_SID") if [[ -z "$CDB_DATAFILE_PATH" ]]; then log "Error getting CDB datafile path" exit 1 fi log "CDB datafile path: $CDB_DATAFILE_PATH" NONCDB_DIR=$(dirname "$NONCDB_DATAFILE_PATH") CDB_DIR=$(dirname "$CDB_DATAFILE_PATH") log "Non-CDB directory: $NONCDB_DIR" log "CDB directory: $CDB_DIR" set_current_state "DATAFILE_PATHS_RETRIEVED" CURRENT_STATE="DATAFILE_PATHS_RETRIEVED")
if [[ "$CURRENT_STATE" == "DB_TYPES_CHECKED" ]]; then time_step "Step 3: Getting Datafile Paths." step3_codefi
# --- Step 4: Non CDB Preparation ---step4_code=( log "Step 4: Non-CDB Preparation." prompt_user "Proceed with non-CDB preparation?" execute_sql_command "alter database open read only" "$NONCDB_SID" # Validate open mode mode=$(sqlplus -s "/ as sysdba" <<-EOF set heading off feedback off pagesize 0 select open_mode from v\\$database; exitEOF ) if [[ "$mode" != *"READ ONLY"* ]]; then log "Error: Non-CDB is not in READ ONLY mode after command. Current mode: $mode" exit 1 fi execute_sql_command "exec dbms_pdb.describe(pdb_descr_file=>'/tmp/new_pdb.xml');" "$NONCDB_SID" execute_sql_command "shutdown immediate;" "$NONCDB_SID" set_current_state "NONCDB_PREPARED" CURRENT_STATE="NONCDB_PREPARED")
if [[ "$CURRENT_STATE" == "DATAFILE_PATHS_RETRIEVED" ]]; then time_step "Step 4: Non-CDB Preparation." step4_codefi
# --- Step 5: Create PDB ---step5_code=( log "Step 5: Create PDB." prompt_user "Proceed with PDB creation?" PDB_NAME=PDBNEW NEW_LOCATION="$CDB_DIR/$PDB_NAME" # Prompt for method echo "Choose the method for PDB creation:" echo "1. nocopy (default)" echo "2. copy" echo "3. move" read -p "Enter your choice (1-3, default 1): " method_choice case "$method_choice" in 2) METHOD="copy" ;; 3) METHOD="move" ;; *) METHOD="nocopy" ;; esac case "$METHOD" in nocopy) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' NOCOPY;" "$CDB_SID" ;; copy) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' COPY file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID" ;; move) execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' MOVE file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID" ;; esac set_current_state "PDB_CREATED" CURRENT_STATE="PDB_CREATED")
if [[ "$CURRENT_STATE" == "NONCDB_PREPARED" ]]; then time_step "Step 5: Create PDB." step5_codefi
# --- Step 6: Post conversion process ---step6_code=( log "Step 6: Post PDB creation process" prompt_user "Proceed with post PDB creation process?" execute_sql_command "alter pluggable database $PDB_NAME open read write;" "$CDB_SID" execute_sql_command "@\$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql;" "$PDB_NAME" set_current_state "COMPLETE" CURRENT_STATE="COMPLETE")
if [[ "$CURRENT_STATE" == "PDB_CREATED" ]]; then time_step "Step 6: Post PDB creation process" step6_codefi
# --- Finalization ---if [[ "$CURRENT_STATE" == "COMPLETE" ]]; then log "Conversion completed successfully." log "You should verify that everything is working properly." rm -f "$SCRIPT_STATE_FILE"else log "Conversion failed or was interrupted at state: $CURRENT_STATE" log "You can restart the script to continue."fi
if (( TOTAL_TIME > 60 )); then log "Total time for the entire procedure: $((TOTAL_TIME / 60)) minutes and $((TOTAL_TIME % 60)) seconds"else log "Total time for the entire procedure: $TOTAL_TIME seconds"fi
log "Script finished."exit 0
#!/bin/bash
# --- Configuration ---
LOG_FILE="noncdb_to_pdb_conversion.log"
SCRIPT_STATE_FILE="conversion_state.txt"
PROMPT_USER=true
TEST_MODE=false
# --- Parse arguments ---
for arg in "$@"; do
case "$arg" in
--test) TEST_MODE=true ;;
--auto) PROMPT_USER=false ;;
esac
done
# --- Logging ---
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
# --- Prompt user for yes/no ---
prompt_user() {
if [[ "$PROMPT_USER" == "true" ]]; then
local response
while true; do
read -p "$1 (yes/no): " response
case "$response" in
[yY][eE][sS]) log "User confirmed: $1"; return 0 ;;
[nN][oO]) log "User rejected: $1"; log "Exiting script."; exit 1 ;;
*) echo "Invalid input. Please enter 'yes' or 'no'." ;;
esac
done
else
log "Automatic: $1"
return 0
fi
}
# --- Get current state ---
get_current_state() {
[[ -f "$SCRIPT_STATE_FILE" ]] && cat "$SCRIPT_STATE_FILE" || echo "START"
}
set_current_state() {
echo "$1" > "$SCRIPT_STATE_FILE"
}
# --- Get SIDs from PMON ---
get_sids_from_pmon() {
ps -ef | grep pmon | grep -v grep | grep -iv asm | grep -iv apx | awk '{print $8}' | awk -F "_" '{print $3}'
}
# --- Choose SID from list ---
choose_sid() {
local options=("$@")
local num_options=${#options[@]}
if (( num_options == 0 )); then
log "No SIDs provided to choose from."
exit 1
fi
echo "Please choose a SID:"
for ((i=0; i<num_options; i++)); do
echo "$((i+1)) - ${options[$i]}"
done
while true; do
read -p "Enter your choice (1-$num_options): " choice
if [[ "$choice" =~ ^[1-9][0-9]*$ ]] && (( choice > 0 && choice <= num_options )); then
echo "${options[$((choice-1))]}"
return 0
else
echo "Invalid choice. Please enter a number between 1 and $num_options."
fi
done
}
# --- Check if DB is CDB ---
is_cdb() {
local sid="$1"
export ORACLE_SID="$sid"
local result=$(sqlplus -s "/ as sysdba" <<-EOF
set heading off feedback off pagesize 0
select cdb from v\\$database;
exit
EOF
)
[[ "$result" == "YES" ]]
}
# --- Get datafile path ---
get_datafile_path() {
local sid="$1"
export ORACLE_SID="$sid"
sqlplus -s "/ as sysdba" <<-EOF
set heading off feedback off pagesize 0
select name from v\\$datafile where rownum=1;
exit
EOF
}
# --- Check open mode ---
get_open_mode() {
local sid="$1"
export ORACLE_SID="$sid"
sqlplus -s "/ as sysdba" <<-EOF
set heading off feedback off pagesize 0
select open_mode from v\\$database;
exit
EOF
}
# --- Execute SQL with error/state check and test mode ---
execute_sql_command() {
local sql_command="$1"
local sid="$2"
export ORACLE_SID="$sid"
local start_time=$(date +%s)
if [[ "$TEST_MODE" == "true" ]]; then
log "[TEST MODE] Would execute SQL: $sql_command for database: $sid"
sqlplus -s "/ as sysdba" <<-EOF
select 1 from dual;
exit;
EOF
return 0
fi
log "Executing SQL command: $sql_command for database: $sid"
sqlplus -s "/ as sysdba" <<-EOF
WHENEVER SQLERROR EXIT FAILURE;
$sql_command;
exit;
EOF
local status=$?
local end_time=$(date +%s)
local duration=$((end_time - start_time))
if [[ "$status" -eq 0 ]]; then
log "SQL command for $sid succeeded."
else
log "SQL command for $sid failed."
exit 1
fi
if (( duration > 60 )); then
log "SQL command took $((duration / 60)) minutes and $((duration % 60)) seconds to complete."
else
log "SQL command took $duration seconds to complete."
fi
((TOTAL_TIME+=duration))
}
# --- Choose PDB creation method ---
choose_method() {
if [[ "$TEST_MODE" == "true" ]]; then
echo "nocopy"
log "[TEST MODE] Defaulting method to nocopy"
return
fi
echo "Choose the method for PDB creation:"
echo "1. nocopy (default)"
echo "2. copy"
echo "3. move"
read -p "Enter your choice (1-3, default 1): " method_choice
case "$method_choice" in
2) echo "copy" ;;
3) echo "move" ;;
*) echo "nocopy" ;;
esac
}
# --- Main Script Start ---
> "$LOG_FILE"
log "Script started."
TOTAL_TIME=0
# Check for Oracle environment
if [[ -z "$ORACLE_HOME" ]]; then
log "Error: ORACLE_HOME must be set."
exit 1
fi
log "ORACLE_HOME: $ORACLE_HOME"
# Interactive mode prompt
if [[ "$TEST_MODE" == "false" ]]; then
prompt_user "Do you want to run in interactive mode (yes/no)?"
[[ "$REPLY" =~ ^[nN] ]] && PROMPT_USER=false
fi
log "Interactive Mode set to: $PROMPT_USER"
log "Test Mode set to: $TEST_MODE"
CURRENT_STATE=$(get_current_state)
log "Current state: $CURRENT_STATE"
# --- Step 1: Find PMON processes and select SIDs ---
if [[ "$CURRENT_STATE" == "START" ]]; then
log "Step 1: Finding PMON processes."
prompt_user "Proceed with finding PMON processes?"
mapfile -t SIDS < <(get_sids_from_pmon)
PMON_COUNT=${#SIDS[@]}
log "Found $PMON_COUNT PMON processes: ${SIDS[*]}"
if (( PMON_COUNT < 2 )); then
log "Error: Less than 2 PMON processes found. Need a non-CDB and a CDB running."
exit 1
fi
if (( PMON_COUNT > 2 )); then
log "More than 2 SIDs detected: ${SIDS[*]}"
log "The script requires 1 CDB and 1 NON CDB for the procedure."
CDB_SID=$(choose_sid "${SIDS[@]}")
NONCDB_SID=$(choose_sid "${SIDS[@]/$CDB_SID}")
log "User chosen CDB_SID: $CDB_SID"
log "User chosen NONCDB_SID: $NONCDB_SID"
else
# Try to auto-detect which is CDB and which is non-CDB
if is_cdb "${SIDS[0]}"; then
CDB_SID="${SIDS[0]}"
NONCDB_SID="${SIDS[1]}"
else
CDB_SID="${SIDS[1]}"
NONCDB_SID="${SIDS[0]}"
fi
log "Automatically selected CDB_SID: $CDB_SID"
log "Automatically selected NONCDB_SID: $NONCDB_SID"
fi
set_current_state "SIDS_SELECTED"
CURRENT_STATE="SIDS_SELECTED"
fi
# --- Step 2: Check CDB vs Non-CDB ---
if [[ "$CURRENT_STATE" == "SIDS_SELECTED" ]]; then
log "Step 2: Checking CDB vs. Non-CDB."
prompt_user "Proceed with checking CDB vs. Non-CDB?"
if ! is_cdb "$CDB_SID"; then
log "Error: $CDB_SID is not a CDB."
exit 1
fi
if is_cdb "$NONCDB_SID"; then
log "Error: $NONCDB_SID is a CDB."
exit 1
fi
log "CDB_SID: $CDB_SID"
log "NONCDB_SID: $NONCDB_SID"
set_current_state "DB_TYPES_CHECKED"
CURRENT_STATE="DB_TYPES_CHECKED"
fi
# --- Step 3: Get Datafile Paths ---
if [[ "$CURRENT_STATE" == "DB_TYPES_CHECKED" ]]; then
log "Step 3: Getting Datafile Paths."
prompt_user "Proceed with getting datafile paths?"
NONCDB_DATAFILE_PATH=$(get_datafile_path "$NONCDB_SID")
if [[ -z "$NONCDB_DATAFILE_PATH" ]]; then
log "Error getting non-CDB datafile path"
exit 1
fi
log "Non-CDB datafile path: $NONCDB_DATAFILE_PATH"
CDB_DATAFILE_PATH=$(get_datafile_path "$CDB_SID")
if [[ -z "$CDB_DATAFILE_PATH" ]]; then
log "Error getting CDB datafile path"
exit 1
fi
log "CDB datafile path: $CDB_DATAFILE_PATH"
NONCDB_DIR=$(dirname "$NONCDB_DATAFILE_PATH")
CDB_DIR=$(dirname "$CDB_DATAFILE_PATH")
log "Non-CDB directory: $NONCDB_DIR"
log "CDB directory: $CDB_DIR"
set_current_state "DATAFILE_PATHS_RETRIEVED"
CURRENT_STATE="DATAFILE_PATHS_RETRIEVED"
fi
# --- Step 4: Non CDB Preparation ---
if [[ "$CURRENT_STATE" == "DATAFILE_PATHS_RETRIEVED" ]]; then
log "Step 4: Non-CDB Preparation."
prompt_user "Proceed with non-CDB preparation?"
execute_sql_command "alter database open read only" "$NONCDB_SID"
# Validate open mode
mode=$(get_open_mode "$NONCDB_SID")
if [[ "$mode" != *"READ ONLY"* ]]; then
log "Error: Non-CDB is not in READ ONLY mode after command. Current mode: $mode"
exit 1
fi
execute_sql_command "exec dbms_pdb.describe(pdb_descr_file=>'/tmp/new_pdb.xml');" "$NONCDB_SID"
execute_sql_command "shutdown immediate;" "$NONCDB_SID"
set_current_state "NONCDB_PREPARED"
CURRENT_STATE="NONCDB_PREPARED"
fi
# --- Step 5: Create PDB ---
if [[ "$CURRENT_STATE" == "NONCDB_PREPARED" ]]; then
log "Step 5: Create PDB."
prompt_user "Proceed with PDB creation?"
PDB_NAME=PDBNEW
NEW_LOCATION="$CDB_DIR/$PDB_NAME"
METHOD=$(choose_method)
case "$METHOD" in
nocopy)
execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' NOCOPY;" "$CDB_SID"
;;
copy)
execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' COPY file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID"
;;
move)
execute_sql_command "CREATE PLUGGABLE DATABASE $PDB_NAME USING '/tmp/new_pdb.xml' MOVE file_name_convert=('$NONCDB_DIR', '$NEW_LOCATION');" "$CDB_SID"
;;
esac
set_current_state "PDB_CREATED"
CURRENT_STATE="PDB_CREATED"
fi
# --- Step 6: Post conversion process ---
if [[ "$CURRENT_STATE" == "PDB_CREATED" ]]; then
log "Step 6: Post PDB creation process"
prompt_user "Proceed with post PDB creation process?"
execute_sql_command "alter pluggable database $PDB_NAME open read write;" "$CDB_SID"
execute_sql_command "@\$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql;" "$PDB_NAME"
set_current_state "COMPLETE"
CURRENT_STATE="COMPLETE"
fi
# --- Finalization ---
if [[ "$CURRENT_STATE" == "COMPLETE" ]]; then
log "Conversion completed successfully."
log "You should verify that everything is working properly."
rm -f "$SCRIPT_STATE_FILE"
else
log "Conversion failed or was interrupted at state: $CURRENT_STATE"
log "You can restart the script to continue."
fi
if (( TOTAL_TIME > 60 )); then
log "Total time for the entire procedure: $((TOTAL_TIME / 60)) minutes and $((TOTAL_TIME % 60)) seconds"
else
log "Total time for the entire procedure: $TOTAL_TIME seconds"
fi
log "Script finished."
exit 0
===raj
#!/bin/bash# Oracle CPU Capacity Report with Solid Validation# Version 2.4 - Robust Output Parsing
REPORT_FILE="/tmp/cpu_capacity_report_$(date +%Y%m%d_%H%M%S).txt"VALIDATION_FILE="/tmp/cpu_validation_$(date +%Y%m%d_%H%M%S).log"
# Improved SQL execution functionget_sql_value() { local sql=$1 local sid=$2 ORACLE_SID=$sid sqlplus -s / as sysdba <<EOF | awk '/^[[:space:]]*[0-9]/{print $1; exit} /^[[:space:]]*-/{print $2; exit}'set pagesize 0set feedback offset heading off$sqlEOF}
# Function to get safe numeric valuesafe_number() { local num=$1 if [[ $num =~ ^[+-]?[0-9]+\.?[0-9]*$ ]]; then echo "$num" else echo "0" fi}
# Function to validate calculationsvalidate_cpu_metrics() { local total_cores=$1 local system_usage=$2 local db_usage=$3 local os_usage=$4 echo "CPU METRICS VALIDATION" > $VALIDATION_FILE echo "======================" >> $VALIDATION_FILE echo "Validation Time: $(date)" >> $VALIDATION_FILE echo "" >> $VALIDATION_FILE # Rule 1: System + Available = Total local calculated_total=$(echo "$system_usage + $available_cores" | bc) if [ "$(echo "$calculated_total == $total_cores" | bc -l)" -eq 1 ]; then echo "[✓] System + Available = Total" >> $VALIDATION_FILE echo " $system_usage (System) + $available_cores (Available) = $total_cores (Total)" >> $VALIDATION_FILE else echo "[✗] System + Available ≠ Total" >> $VALIDATION_FILE echo " $system_usage + $available_cores = $calculated_total (expected $total_cores)" >> $VALIDATION_FILE fi # Rule 2: DB + OS = System local calculated_system=$(echo "$db_usage + $os_usage" | bc) if [ "$(echo "$calculated_system == $system_usage" | bc -l)" -eq 1 ]; then echo "[✓] DB + OS = System Usage" >> $VALIDATION_FILE echo " $db_usage (DB) + $os_usage (OS) = $system_usage (System)" >> $VALIDATION_FILE else echo "[✗] DB + OS ≠ System Usage" >> $VALIDATION_FILE echo " $db_usage + $os_usage = $calculated_system (expected $system_usage)" >> $VALIDATION_FILE echo " Difference: $(echo "$system_usage - $calculated_system" | bc) cores unaccounted" >> $VALIDATION_FILE fi # Rule 3: Percentages sum to 100% local total_pct=$(echo "$system_usage_pct + $available_pct" | bc) if [ "$(echo "$total_pct == 100" | bc -l)" -eq 1 ]; then echo "[✓] System% + Available% = 100%" >> $VALIDATION_FILE echo " $system_usage_pct% + $available_pct% = 100%" >> $VALIDATION_FILE else echo "[✗] System% + Available% ≠ 100%" >> $VALIDATION_FILE echo " $system_usage_pct% + $available_pct% = $total_pct%" >> $VALIDATION_FILE fi echo "" >> $VALIDATION_FILE echo "VALIDATION NOTES:" >> $VALIDATION_FILE echo "1. Minor discrepancies (<0.5%) may be due to timing differences in metric collection" >> $VALIDATION_FILE echo "2. Large differences indicate either measurement errors or unaccounted CPU usage" >> $VALIDATION_FILE}
# Get system CPU metricsTOTAL_CORES=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo)CPU_USAGE_PCT=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8}' | cut -d. -f1)SYSTEM_CPU=$(echo "scale=2; $CPU_USAGE_PCT * $TOTAL_CORES / 100" | bc)
# Get database CPU usageDATABASES=$(ps -eo command | grep -E '[p]mon|[_]pmon' | awk -F_ '{print $NF}' | sort | uniq)TOTAL_DB_CPU=0
for DB in $DATABASES; do DB_CPU_CENTISEC=$(get_sql_value "SELECT ROUND(SUM(value)) FROM v\$sysmetric WHERE metric_name='CPU Usage Per Sec' AND group_id=2;" "$DB") DB_CPU_CENTISEC=$(safe_number "$DB_CPU_CENTISEC") DB_CPU=$(echo "scale=2; $DB_CPU_CENTISEC / 100" | bc) TOTAL_DB_CPU=$(echo "$TOTAL_DB_CPU + $DB_CPU" | bc)done
# Calculate derived metricsOTHER_CPU=$(echo "scale=2; $SYSTEM_CPU - $TOTAL_DB_CPU" | bc)AVAILABLE_CPU=$(echo "scale=2; $TOTAL_CORES - $SYSTEM_CPU" | bc)AVAILABLE_PCT=$(echo "scale=2; 100 - $CPU_USAGE_PCT" | bc)
# Run validationvalidate_cpu_metrics "$TOTAL_CORES" "$SYSTEM_CPU" "$TOTAL_DB_CPU" "$OTHER_CPU"
# Generate report{echo "ORACLE CPU CAPACITY REPORT WITH VALIDATION"echo "========================================="echo "Generated: $(date)"echo ""echo "1. SYSTEM RESOURCES"echo "-------------------"echo " Total CPU Cores : $TOTAL_CORES"echo " System CPU Usage : $SYSTEM_CPU cores ($CPU_USAGE_PCT%)"echo " - Database Usage : $TOTAL_DB_CPU cores"echo " - OS/Other Usage : $OTHER_CPU cores"echo " Available Cores : $AVAILABLE_CPU cores ($AVAILABLE_PCT%)"echo ""echo "2. VALIDATION SUMMARY"echo "---------------------"grep -E '^\[[✓✗]\]' "$VALIDATION_FILE"echo ""echo "3. DETAILED METRICS VALIDATION"echo "------------------------------"cat "$VALIDATION_FILE"} > "$REPORT_FILE"
echo "Report generated: $REPORT_FILE"echo "Validation details: $VALIDATION_FILE"
#!/bin/bash# Oracle CPU Capacity Report with Validation# Version 2.3 - Includes Cross-Verification
REPORT_FILE="/tmp/cpu_capacity_report_$(date +%Y%m%d_%H%M%S).txt"VALIDATION_FILE="/tmp/cpu_validation_$(date +%Y%m%d_%H%M%S).log"
# Function to validate calculationsvalidate_cpu_metrics() { local total_cores=$1 local system_usage=$2 local db_usage=$3 local os_usage=$4 echo "VALIDATION REPORT" > $VALIDATION_FILE echo "=================" >> $VALIDATION_FILE echo "Timestamp: $(date)" >> $VALIDATION_FILE echo "" >> $VALIDATION_FILE # Rule 1: System + Available should equal Total local calculated_total=$(echo "$system_usage + $available_cores" | bc) if [ "$(echo "$calculated_total == $total_cores" | bc)" -eq 1 ]; then echo "[PASS] System + Available = Total: $system_usage + $available_cores = $total_cores" >> $VALIDATION_FILE else echo "[FAIL] System + Available ($system_usage + $available_cores) != Total ($total_cores)" >> $VALIDATION_FILE fi # Rule 2: DB + OS should equal System local calculated_system=$(echo "$db_usage + $os_usage" | bc) if [ "$(echo "$calculated_system == $system_usage" | bc)" -eq 1 ]; then echo "[PASS] DB + OS = System: $db_usage + $os_usage = $system_usage" >> $VALIDATION_FILE else echo "[FAIL] DB + OS ($db_usage + $os_usage) != System ($system_usage)" >> $VALIDATION_FILE echo " Difference: $(echo "$system_usage - ($db_usage + $os_usage)" | bc) cores" >> $VALIDATION_FILE fi # Rule 3: Percentages should sum to 100% local total_pct=$(echo "$system_usage_pct + $available_pct" | bc) if [ "$(echo "$total_pct == 100" | bc)" -eq 1 ]; then echo "[PASS] System% + Available% = 100%" >> $VALIDATION_FILE else echo "[FAIL] System% ($system_usage_pct) + Available% ($available_pct) = $total_pct%" >> $VALIDATION_FILE fi echo "" >> $VALIDATION_FILE echo "Note: Small discrepancies may occur due to timing differences in metric collection" >> $VALIDATION_FILE}
# Get accurate CPU metricsTOTAL_CORES=$(grep -c ^processor /proc/cpuinfo)CPU_USAGE_PCT=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')SYSTEM_CPU=$(echo "scale=2; $CPU_USAGE_PCT * $TOTAL_CORES / 100" | bc)
# Get database CPU usageDATABASES=$(ps -eo command | grep -E '[p]mon|[_]pmon' | awk -F_ '{print $NF}' | sort | uniq)TOTAL_DB_CPU=0for DB in $DATABASES; do export ORACLE_SID=$DB DB_CPU_CENTISEC=$(sqlplus -s / as sysdba <<EOF | awk '/^ / {print $1}'set pagesize 0set feedback offset heading offSELECT ROUND(SUM(value)) FROM v\$sysmetric WHERE metric_name='CPU Usage Per Sec' AND group_id=2;EOF) [ -z "$DB_CPU_CENTISEC" ] && DB_CPU_CENTISEC=0 TOTAL_DB_CPU=$(echo "scale=2; $TOTAL_DB_CPU + ($DB_CPU_CENTISEC / 100)" | bc)done
# Calculate derived metricsOTHER_CPU=$(echo "scale=2; $SYSTEM_CPU - $TOTAL_DB_CPU" | bc)AVAILABLE_CPU=$(echo "scale=2; $TOTAL_CORES - $SYSTEM_CPU" | bc)AVAILABLE_PCT=$(echo "scale=2; 100 - $CPU_USAGE_PCT" | bc)
# Run validationvalidate_cpu_metrics $TOTAL_CORES $SYSTEM_CPU $TOTAL_DB_CPU $OTHER_CPU
# Generate reportecho "CPU CAPACITY REPORT WITH VALIDATION" > $REPORT_FILEecho "===================================" >> $REPORT_FILEecho "Generated: $(date)" >> $REPORT_FILEecho "" >> $REPORT_FILE
echo "1. SYSTEM RESOURCES" >> $REPORT_FILEecho "-------------------" >> $REPORT_FILEecho " Total CPU Cores : $TOTAL_CORES" >> $REPORT_FILEecho " System CPU Usage : $SYSTEM_CPU cores ($CPU_USAGE_PCT%)" >> $REPORT_FILEecho " - Database Usage : $TOTAL_DB_CPU cores" >> $REPORT_FILEecho " - OS/Other Usage : $OTHER_CPU cores" >> $REPORT_FILEecho " Available Cores : $AVAILABLE_CPU cores ($AVAILABLE_PCT%)" >> $REPORT_FILEecho "" >> $REPORT_FILE
echo "2. VALIDATION SUMMARY" >> $REPORT_FILEecho "---------------------" >> $REPORT_FILEgrep -E '^\[(PASS|FAIL)\]' $VALIDATION_FILE >> $REPORT_FILEecho "" >> $REPORT_FILE
echo "3. DETAILED VALIDATION" >> $REPORT_FILEecho "----------------------" >> $REPORT_FILEcat $VALIDATION_FILE >> $REPORT_FILE
echo "" >> $REPORT_FILEecho "Report generated: $REPORT_FILE" >> $REPORT_FILEecho "Validation log: $VALIDATION_FILE" >> $REPORT_FILE
echo "CPU report with validation generated:"echo $REPORT_FILEecho "Validation details:"echo $VALIDATION_FILE
RAJ===
#!/bin/bash
# filepath: /path/to/cpu_analysis.sh
# Set environment variablesLOG_FOLDER="/x/home/oracle/admin/scripts/logs/cpu_analysis"mkdir -p "$LOG_FOLDER"
# Oracle environment variables (update as per your environment)source ~/.profile
# Temporary filesTOTAL_CPUS_FILE="$LOG_FOLDER/total_cpus.txt"SYSTEM_CPU_USAGE_FILE="$LOG_FOLDER/system_cpu_usage.txt"DATABASE_COUNT_FILE="$LOG_FOLDER/database_count.txt"DATABASE_LIST_FILE="$LOG_FOLDER/database_list.txt"DATABASE_CPU_USAGE_FILE="$LOG_FOLDER/database_cpu_usage.txt"CAPACITY_FILE="$LOG_FOLDER/capacity.txt"
# Function to get total number of CPUs on the hostget_total_cpus() { grep -c ^processor /proc/cpuinfo > "$TOTAL_CPUS_FILE"}
# Function to get system-level CPU usageget_system_cpu_usage() { mpstat -P ALL 1 1 | awk '/all/ {print 100 - $NF}' > "$SYSTEM_CPU_USAGE_FILE"}
# Function to get the number of databases on the hostget_number_of_databases() { sqlplus -s / as sysdba <<EOF > "$DATABASE_COUNT_FILE"SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFFSELECT COUNT(*) FROM v\$database;EXIT;EOF}
# Function to get list of databasesget_database_list() { sqlplus -s / as sysdba <<EOF > "$DATABASE_LIST_FILE"SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFFSELECT name FROM v\$database;EXIT;EOF}
# Function to get CPU usage for each databaseget_database_cpu_usage() { databases=$(cat "$DATABASE_LIST_FILE") > "$DATABASE_CPU_USAGE_FILE" for db in $databases; do echo "Database: $db" >> "$DATABASE_CPU_USAGE_FILE" sqlplus -s / as sysdba <<EOF >> "$DATABASE_CPU_USAGE_FILE"SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFFSELECT ROUND(SUM(VALUE) / COUNT(*), 2) FROM v\$sysmetric WHERE METRIC_NAME = 'Host CPU Utilization (%)' AND BEGIN_TIME > SYSDATE - 1/24;EXIT;EOF done}
# Function to calculate current available capacitycalculate_capacity() { total_cpus=$(cat "$TOTAL_CPUS_FILE") used_capacity=$(cat "$SYSTEM_CPU_USAGE_FILE") available_capacity=$(echo "$total_cpus - $used_capacity" | bc) echo "Current available capacity (CPUs): $available_capacity" > "$CAPACITY_FILE" echo "Total used capacity (CPUs): $used_capacity" >> "$CAPACITY_FILE"}
# Function to print the reportprint_report() { echo "==================== CPU Analysis Report ====================" echo "Date: $(date)" echo "-------------------------------------------------------------" echo "Total number of CPUs on the host: $(cat "$TOTAL_CPUS_FILE")" echo "-------------------------------------------------------------" echo "System CPU Usage:" echo " - Number of CPUs currently in use: $(cat "$SYSTEM_CPU_USAGE_FILE")" echo " - Percentage of CPU being used: $(cat "$SYSTEM_CPU_USAGE_FILE")%" echo "-------------------------------------------------------------" echo "Number of databases on the host: $(cat "$DATABASE_COUNT_FILE")" echo "-------------------------------------------------------------" echo "Database CPU Usage:" cat "$DATABASE_CPU_USAGE_FILE" | while read line; do echo " $line" done echo "-------------------------------------------------------------" echo "Capacity Analysis:" cat "$CAPACITY_FILE" | while read line; do echo " $line" done echo "============================================================="}
# Main functionmain() { # Get total number of CPUs get_total_cpus
# Get system-level CPU usage get_system_cpu_usage
# Get number of databases get_number_of_databases
# Get CPU usage for each database get_database_list get_database_cpu_usage
# Calculate current available capacity calculate_capacity
# Print the report print_report}
# Run the main functionmain
DECLARE
users_to_lock SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('abc', 'def', 'ghi', 'jkl', 'mno');
account_status VARCHAR2(30);
BEGIN
FOR i IN 1 .. users_to_lock.COUNT LOOP
BEGIN
EXECUTE IMMEDIATE 'ALTER USER ' || users_to_lock(i) || ' ACCOUNT LOCK';
-- Check the account status after attempting to lock
SELECT account_status INTO account_status
FROM dba_users
WHERE username = UPPER(users_to_lock(i));
IF account_status = 'LOCKED' THEN
DBMS_OUTPUT.PUT_LINE('User ' || users_to_lock(i) || ' is now locked.');
ELSE
DBMS_OUTPUT.PUT_LINE('User ' || users_to_lock(i) || ' is not locked.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('User ' || users_to_lock(i) || ' does not exist.');
WHEN OTHERS THEN
IF SQLCODE = -1918 THEN
DBMS_OUTPUT.PUT_LINE('User ' || users_to_lock(i) || ' does not exist.');
ELSE
DBMS_OUTPUT.PUT_LINE('An unexpected error occurred for user ' || users_to_lock(i) || '.');
END IF;
END;
END LOOP;
END;
/
DECLARE
users_to_check SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('abc', 'def', 'ghi', 'jkl', 'mno');
account_status VARCHAR2(30);
BEGIN
FOR i IN 1 .. users_to_check.COUNT LOOP
BEGIN
SELECT account_status INTO account_status
FROM dba_users
WHERE username = UPPER(users_to_check(i));
DBMS_OUTPUT.PUT_LINE('User ' || users_to_check(i) || ' is ' || account_status || '.');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('User ' || users_to_check(i) || ' does not exist.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An unexpected error occurred for user ' || users_to_check(i) || '.');
END;
END LOOP;
END;
/
Yes, you can achieve this by checking if the user exists before attempting to lock the account. Here's how you can modify your SQL to handle this and send it as a single statement:
To enhance the document for the "move" method in the context of converting a non-CDB to a CDB, we need to outline the specific steps, benefits, and considerations associated with this approach. The "move" method involves relocating datafiles without copying them, similar to the NOCOPY method, but with additional considerations for file management and metadata updates.
Enhanced Document: Non-CDB to CDB Conversion Using MOVE Method
Internal Actions:
CREATE PLUGGABLE DATABASE Statement:
- This command is used within the CDB to initiate the creation of the new PDB using the MOVE method.
XML File Parsing:
- Oracle reads and parses the new_pdb.xml file generated earlier to understand the structure and metadata of the non-CDB.
PDB Creation:
- A new PDB entry is created in the CDB's data dictionary.
Tablespace and Datafile Setup:
- Based on the XML file:
- New tablespaces are created within the CDB to match the tablespaces found in the XML.
- Datafiles are moved from the non-CDB location to the CDB location, updating paths as necessary.
- Based on the XML file:
Metadata Update:
- Oracle updates the metadata in the new PDB to reference the moved datafiles. The path is modified using the file_name_convert clause.
Shared Files:
- The PDB now uses the moved datafiles, which are no longer associated with the original non-CDB.
Control File:
- The PDB will get its own control file, separate from the non-CDB.
Object Recreation:
- Database objects (tables, views, etc.) are recreated inside the PDB based on the XML metadata.
User Accounts:
- User accounts, roles, and privileges are created and assigned within the PDB.
PDB Status:
- The new PDB is created in a MOUNTED state. It is not yet OPEN.
Log Files:
- The new PDB will have its own redo log files, separate from the CDB and other PDBs.
Undo Tablespace:
- The new PDB will have its own undo tablespace.
Temporary Tablespace:
- The new PDB will have its own temporary tablespace.
Original Non-CDB Data Files:
- The original non-CDB data files are now considered to belong to the PDB.
Pros:
- Speed: The conversion is fast because files are moved rather than copied.
- Storage Efficiency: No additional storage space is required, as the original datafiles are moved.
Cons:
- Risk to Original Data: The PDB now uses the moved non-CDB datafiles. Any corruption within the PDB could affect the data within the moved files.
- Complex Rollback: Rolling back to the original non-CDB is significantly more complex and risky.
- Interdependency: If the PDB is dropped, the files are also dropped, as they are now considered to belong to the PDB.
Rollback for MOVE
Warning: Rollback for MOVE is complicated and carries a significant risk of data loss if not performed carefully.
Stop and Drop the PDB:
- If the PDB is open, you must close it.
- Drop the PDB, including datafiles.
Verification (Critical):
- Check oldspec: Even though you executed the drop including datafiles, the files under oldspec were dropped. They were considered part of the PDB.
Recover from Backup:
- If the files were dropped, you have to restore them from backup. If you didn't make a backup of the files, there is no way to recover them.
Recover to a New Name:
- If you don't have a backup of the non-CDB, you can try to start the non-CDB as a new database, with a new name.
Clean Up:
- Remove any new files created, like log files and undo tablespace.
- Try to start the non-CDB again.
Phase 3: Post-Creation Cleanup:
- Run a cleanup to get rid of non-CDB items in the new pluggable database using @$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql.
Internal Actions:
- Script Execution: The noncdb_to_pdb.sql script is designed to remove remnants of the non-CDB structure from the newly created PDB.
- SYS Connection: This script needs to be run connected as a user with SYSDBA privileges, and connected to the PDB.
- Script Actions: The specific actions in the script are version-dependent, but they generally include:
- Invalidating Obsolete Objects: It might drop or invalidate some objects that are no longer relevant in the PDB environment.
- Removing Non-PDB User: It likely removes the database user SYSBACKUP, as well as other database objects that are no longer used in a PDB environment.
- Updating Dictionary: It modifies some data dictionary information to correctly reflect the PDB's identity.
- Resource Management: It modifies some parameters in the database to suit it to the new PDB environment.
- Cleaning up: Removes data, settings, and items that are no longer used.
- Recompiles: Recompile invalid objects.
Why it is Important:
This step is vital for a clean conversion. It ensures that the PDB is properly integrated into the CDB environment and doesn't retain unnecessary or conflicting information from the original non-CDB. This cleanup script should be run in the PDB, and not in the CDB.
Method 1: COPY vs Method 2: NOCOPY vs Method 3: MOVE - Summary Table
Feature | COPY | NOCOPY | MOVE |
---|---|---|---|
Datafiles | Copied to new location. | Reused from the original non-CDB. | Moved from original non-CDB. |
Speed | Slower (due to file copy). | Faster (no file copy). | Fast (file move). |
Storage | Requires double the storage initially. | No extra storage initially. | No extra storage initially. |
Original Data | Isolated. Changes in PDB do not affect non-CDB data. | Shared. Changes in PDB can affect non-CDB data (risky). | Shared. Changes in PDB can affect non-CDB data (risky). |
Rollback | Easier: Drop PDB, copied files are removed. Original files untouched. | Difficult & Risky: Requires careful manual intervention. Data loss possible. ORA-01122 errors likely. | Difficult & Risky: Requires careful manual intervention. Data loss possible. |
Risk | Lower risk to original non-CDB data. | Higher risk to original non-CDB data. | Higher risk to original non-CDB data. |
File removal | If the PDB is dropped, only the copied files are removed. | If the PDB is dropped, all files from the old non-CDB are removed. | If the PDB is dropped, all files from the old non-CDB are removed. |
Dependencies | No dependencies with the non-CDB data files. | Strong dependency with non-CDB data files. | Strong dependency with non-CDB data files. |
ORA errors | No errors will happen with the original non-CDB if you shut down the CDB and try to start it. | ORA-01122, ORA-01110, ORA-01204 will happen if you shut down the CDB and try to start the non-CDB. | ORA-01122, ORA-01110, ORA-01204 will happen if you shut down the CDB and try to start the non-CDB. |
Key Points & Considerations:
- Datafile Management: The MOVE method involves relocating datafiles, which requires careful management to ensure paths are updated correctly.
- file_name_convert is Essential: This clause is critical for relocating datafiles to the correct location in the CDB.
- Metadata vs. Data: The DBMS_PDB.DESCRIBE procedure only extracts metadata. The data itself is moved during the CREATE PLUGGABLE DATABASE process.
- Downtime: The non-CDB is unavailable during the SHUTDOWN and data file move. The time required for the move is directly related to the size of the non-CDB's datafiles.
- CDB Requirements: The CDB must have sufficient disk space for the new PDB's datafiles, and it must be running and accessible.
- Non-CDB files: After the conversion, you might decide to keep the non-CDB files as a backup, or remove them (only if you used COPY).
- Compatibility: The Oracle version of the CDB should be the same or later than the non-CDB.
- Backup: Always take a backup of the files before using MOVE.
This enhanced document provides a comprehensive overview of the MOVE method for converting a non-CDB to a CDB, highlighting the internal actions, pros and cons, rollback procedures, and key considerations.
Migrating a non-CDB with Transparent Data Encryption (TDE) enabled to a CDB involves several steps to ensure that encryption keys and encrypted data are properly handled. TDE is used to encrypt data at rest, and it's crucial to manage the encryption keys during the migration process. Below are detailed steps and commands to facilitate this migration:
Pre-Migration Steps
Verify TDE Configuration:
- Ensure that TDE is properly configured in the non-CDB. Check the status of the wallet and the encryption keys.
Backup the Wallet:
- Backup the wallet directory from the non-CDB. This is crucial as the wallet contains the encryption keys.
Backup the Database:
- Perform a full backup of the non-CDB to ensure data safety.
Migration Steps
Prepare the CDB Environment:
- Ensure that the CDB is configured to use TDE. If not, set up TDE in the CDB.
Copy the Wallet:
- Copy the wallet from the non-CDB to the CDB's wallet location.
Open the Wallet in CDB:
- Open the wallet in the CDB to access the encryption keys.
Create Pluggable Database:
- Use the CREATE PLUGGABLE DATABASE command to migrate the non-CDB to a PDB within the CDB.
Verify Encryption in PDB:
- Check that the encryption keys are accessible and that encrypted data is intact in the new PDB.
Post-Migration Steps
Close the Wallet:
- After verifying the migration, close the wallet in the CDB.
Backup the CDB Wallet:
- Backup the wallet in the CDB to ensure encryption keys are safe.
Test the PDB:
- Perform tests to ensure that the PDB is functioning correctly and that encrypted data is accessible.
Cleanup:
- Remove any temporary files or backups that are no longer needed.
Additional Considerations
- Compatibility: Ensure that the Oracle version of the CDB supports TDE and is compatible with the non-CDB.
- Security: Maintain security protocols during the migration, especially when handling encryption keys and wallets.
- Documentation: Document each step of the migration process for future reference and auditing purposes.
By following these detailed steps, you can successfully migrate a non-CDB with TDE enabled to a CDB, ensuring that encryption keys and encrypted data are properly managed throughout the process.
Draj
The script you provided is a Bash script designed to generate a CPU analysis report. It offers several modes and methods for running the report, based on the command-line arguments and options specified. Here are the different ways you can run this script, along with the modes and methods available:
Command-Line Arguments and Options
Interval and Count:
- Interval: The time interval in seconds between each report generation. Default is 1 second.
- Count: The number of times the report is generated. Default is 10.
Usage:
./script.sh [Interval] [Count]
Top N Rows:
- top=: Specifies the number of rows to display in the report. Default is 10.
Usage:
./script.sh top=5
Sort Field:
- sort_field=: Determines the field by which the report is sorted. Options include
CPU_SEC
,AVG_NB_CPU
,MAX_NB_CPU
,MIN_NB_CPU
. Default isCPU_SEC
.
Usage:
./script.sh sort_field=AVG_NB_CPU
- sort_field=: Determines the field by which the report is sorted. Options include
Display User Information:
- displayuser=: Whether to include user information in the report. Options are
Y
(Yes) orN
(No). Default isN
.
Usage:
./script.sh displayuser=Y
- displayuser=: Whether to include user information in the report. Options are
Display Command Information:
- displaycmd=: Whether to include command information in the report. Options are
Y
(Yes) orN
(No). Default isN
.
Usage:
./script.sh displaycmd=Y
- displaycmd=: Whether to include command information in the report. Options are
Help:
- help: Displays usage information and exits.
Usage:
./script.sh help
Combining Options
You can combine these options to customize the report generation. For example:
Example 1: Run the report every 2 seconds, 5 times, displaying the top 5 rows, sorted by average number of CPUs, including user and command information.
Example 2: Run the report with default settings but display command information.