Saturday, May 3, 2025
get_max_thread_by_instance() {
local conns=("$@")
local max_thread=0
for conn in "${conns[@]}"; do
echo "[INFO] Checking instance numbers on: \"$conn\""
local thread_num
thread_num=$(exec_sqlplus "$conn" "
SELECT MAX(instance_number) FROM gv\\$instance;
" | tr -d '[:space:]')
if [[ "$thread_num" =~ ^[0-9]+$ ]] && [[ "$thread_num" -gt "$max_thread" ]]; then
max_thread=$thread_num
fi
done
echo "$max_thread"
}
get_largest_max_thread_from_dbs() {
local conns=("$@")
local max_thread=0
for conn in "${conns[@]}"; do
echo "Checking max thread# on: $conn"
local thread_num
thread_num=$(exec_sqlplus "$conn" "
SELECT MAX(thread#) FROM (
SELECT thread# FROM v\\$log
UNION
SELECT thread# FROM v\\$standby_log
);
" | tr -d '[:space:]')
if [[ "$thread_num" =~ ^[0-9]+$ ]] && [[ "$thread_num" -gt "$max_thread" ]]; then
max_thread=$thread_num
fi
done
echo "$max_thread"
}
# Provide all DBs as arguments
MAX_THREAD=$(get_largest_max_thread_from_dbs "$PRIMARY_CONN" "${STANDBY_CONN_LIST[@]}")
echo " Largest thread# across all databases: $MAX_THREAD"
#!/bin/bash
SYS_PASS="oracle"
STANDBY_CONN="myhost-scan:1521/MYCDB"
exec_sqlplus() {
local conn="$1"
local sql="$2"
echo ">> Connecting to $conn"
echo "SQL: $sql"
}
drop_redo_groups_safely() {
local conn="$1"
shift
local groups=("$@")
echo "DEBUG: conn=$conn"
for g in "${groups[@]}"; do
echo "Would drop group $g on $conn"
done
}
groups=("11" "12" "13")
drop_redo_groups_safely "$STANDBY_CONN" "${groups[@]}"
GROUPS_TO_DROP=$(echo "${STANDBY_REDO_GROUPS_MAP[$STANDBY_CONN]}" | tr ' ' '\n' | awk -F',' '{print $1}')
read -ra GROUP_LIST <<< "$GROUPS_TO_DROP"
drop_redo_groups_safely "$STANDBY_CONN" "${GROUP_LIST[@]}"
drop_redo_groups_safely() {
local CONN="$1"
shift
local GROUPS=("$@")
local DB_ROLE
DB_ROLE=$(exec_sqlplus "$CONN" "SELECT database_role FROM v\\$database;")
for grp in "${GROUPS[@]}"; do
local dropped=0
local attempts=0
while [[ $attempts -lt 5 ]]; do
((attempts++))
if [[ "$DB_ROLE" == "PRIMARY" ]]; then
echo "🔁 [${CONN}] Switching logfile before dropping group $grp (attempt $attempts)..."
exec_sqlplus "$CONN" "ALTER SYSTEM SWITCH LOGFILE;"
sleep 5
fi
echo "⚙️ Attempting to drop redo log group $grp from $CONN (attempt $attempts)..."
exec_sqlplus "$CONN" "ALTER DATABASE DROP LOGFILE GROUP $grp;"
if [[ $? -eq 0 ]]; then
echo "✅ Successfully dropped redo log group $grp from $CONN"
dropped=1
break
else
echo "❌ Failed to drop redo log group $grp on attempt $attempts"
sleep 5
fi
done
if [[ $dropped -eq 0 ]]; then
echo "🛑 Could not drop redo group $grp after 5 attempts on $CONN"
fi
done
}
drop_standby_groups_safely() {
local CONN="$1"
shift
local GROUPS=("$@")
local DB_ROLE
DB_ROLE=$(exec_sqlplus "$CONN" "SELECT database_role FROM v\\$database;")
for grp in "${GROUPS[@]}"; do
local dropped=0
for attempt in {1..5}; do
if [[ "$DB_ROLE" == "PHYSICAL STANDBY" ]]; then
exec_sqlplus "$CONN" "ALTER DATABASE CLEAR LOGFILE GROUP $grp;"
sleep 2
fi
exec_sqlplus "$CONN" "ALTER DATABASE DROP STANDBY LOGFILE GROUP $grp;"
if [[ $? -eq 0 ]]; then
echo "✅ Dropped standby group $grp from $CONN"
dropped=1
break
else
echo "🔁 Failed to drop standby group $grp. Retrying..."
sleep 5
fi
done
if [[ $dropped -eq 0 ]]; then
echo "❌ Could not drop standby group $grp from $CONN after retries."
fi
done
}
#!/bin/bash
# Script: recreate_redologs_enhanced.sh
# Usage: ./recreate_redologs_enhanced.sh
# Initialize environment
INPUT_FILE=$1
LOG_FILE="redo_recreation_$(date +%Y%m%d%H%M%S).log"
TMP_DIR="/tmp/redo_workdir_$(date +%s)"
mkdir -p $TMP_DIR
# Load configuration
source $INPUT_FILE || { echo "Error loading input file"; exit 1; }
# Database connections
PRIMARY_CONN="${SYS_USER}/${SYS_PASSWORD}@${DB_NAME} as sysdba"
STANDBY_DB=$(dgmgrl -silent ${PRIMARY_CONN} < $TMP_DIR/primary_groups.lst
log "Capturing standby database configuration"
capture_groups "$STANDBY_CONN" STANDBY > $TMP_DIR/standby_groups.lst
# Create new groups on both databases
for db_type in PRIMARY STANDBY; do
conn=$([ "$db_type" = "PRIMARY" ] && echo "$PRIMARY_CONN" || echo "$STANDBY_CONN")
input_file=$TMP_DIR/${db_type,,}_groups.lst
# Create primary redo logs
log "Creating new PRIMARY redo logs on $db_type"
awk -F: '/:PRIMARY:/{print $2}' $input_file | sort -nu | while read thread; do
count=$(grep ":PRIMARY:$db_type" $input_file | grep ":$thread:" | wc -l)
create_new_groups "$conn" "PRIMARY" "$NEW_REDO_SIZE" "$thread" "$count"
done
# Create standby redo logs
log "Creating new STANDBY redo logs on $db_type"
awk -F: '/:STANDBY:/{print $2}' $input_file | sort -nu | while read thread; do
count=$(grep ":STANDBY:$db_type" $input_file | grep ":$thread:" | wc -l)
create_new_groups "$conn" "STANDBY" "$NEW_STANDBY_REDO_SIZE" "$thread" "$count"
done
done
# Force log switches to age out old groups
log "Initiating log switches to inactive old groups"
for i in {1..10}; do
sqlplus -S /nolog <