Thursday, November 13, 2025

#!/bin/bash ################################################################################ # Oracle 19c RAC Database Administration - Data Guard Health Functions # Description: Data Guard configuration and health monitoring functions # Created: 2025-11-02 # Updated: 2025-11-14 - Integrated with database loading fix and wrapper functions ################################################################################ ################################################################################ # Function: perform_dg_health_check # Description: Main wrapper function for Data Guard health check # Parameters: $1 - Database name # $2 - SCAN address # $3 - Service name # Returns: 0 on success, 1 on failure ################################################################################ perform_dg_health_check() { local db_name=$1 local scan=$2 local service=$3 log_message "INFO" "Starting Data Guard health check for: ${db_name}" # Validate database connection if ! test_db_connection "${scan}" "${service}"; then log_message "ERROR" "Cannot connect to database ${db_name}" echo "ERROR: Cannot connect to database ${db_name}" return 1 fi # Call the actual health check function show_dg_status "$db_name" return $? } ################################################################################ # Function: show_dg_status # Description: Display comprehensive Data Guard status # Parameters: $1 - Primary database name # Returns: 0 on success, 1 on failure ################################################################################ show_dg_status() { local primary_db=$1 log_message "INFO" "Checking Data Guard status for $primary_db" echo "" echo "==========================================" echo "Data Guard Configuration Status" echo "==========================================" echo "" # Check if DGMGRL is available if ! command -v dgmgrl &> /dev/null; then echo "ERROR: dgmgrl command not found" echo "Data Guard broker may not be configured" log_message "ERROR" "dgmgrl command not available" return 1 fi # Show configuration echo "Data Guard Configuration:" echo "=========================" dgmgrl / << EOF SHOW CONFIGURATION; EXIT; EOF echo "" echo "Database Status:" echo "================" dgmgrl / << EOF SHOW DATABASE VERBOSE $primary_db; EXIT; EOF echo "" # Check for standby databases check_standby_databases "$primary_db" # Check apply lag check_apply_lag "$primary_db" # Check transport lag check_transport_lag "$primary_db" # Generate HTML report generate_dg_health_report "$primary_db" log_message "INFO" "Data Guard status check completed for $primary_db" return 0 } ################################################################################ # Function: check_standby_databases # Description: Check all standby databases in configuration ################################################################################ check_standby_databases() { local primary_db=$1 echo "Standby Database Status:" echo "========================" # Get list of standby databases local standby_dbs=$(dgmgrl / << EOF SET ECHO OFF SHOW CONFIGURATION; EXIT; EOF ) # Parse and check each standby echo "$standby_dbs" | grep -i "physical standby" | while read -r line; do local db_name=$(echo "$line" | awk '{print $1}') echo "" echo "Checking standby: $db_name" echo "------------------------" dgmgrl / << EOF SHOW DATABASE $db_name; EXIT; EOF done echo "" } ################################################################################ # Function: check_apply_lag # Description: Check apply lag on standby databases ################################################################################ check_apply_lag() { local primary_db=$1 echo "Apply Lag Status:" echo "=================" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 SELECT db_unique_name, database_role, TO_CHAR(recovery_timestamp, 'YYYY-MM-DD HH24:MI:SS') as recovery_time, ROUND((SYSDATE - recovery_timestamp) * 24 * 60, 2) as lag_minutes FROM v\$recovery_timestamp; EXIT; EOF echo "" } ################################################################################ # Function: check_transport_lag # Description: Check redo transport lag ################################################################################ check_transport_lag() { local primary_db=$1 echo "Transport Lag Status:" echo "====================" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 SELECT dest_name, status, type, destination, error, TO_CHAR(last_redo_time, 'YYYY-MM-DD HH24:MI:SS') as last_redo_time, ROUND((SYSDATE - last_redo_time) * 24 * 60, 2) as lag_minutes FROM v\$archive_dest_status WHERE status != 'INACTIVE' OR dest_name LIKE 'LOG_ARCHIVE_DEST_%'; EXIT; EOF echo "" } ################################################################################ # Function: generate_dg_health_report # Description: Generate HTML report for Data Guard health ################################################################################ generate_dg_health_report() { local primary_db=$1 local timestamp=$(date '+%Y%m%d_%H%M%S') local report_file="${REPORT_BASE_DIR}/dg_health_${primary_db}_${timestamp}.html" { cat << EOF Data Guard Health Report - $primary_db

Data Guard Health Report

Primary Database: $primary_db

Generated: $(date '+%Y-%m-%d %H:%M:%S')

EOF # Configuration Status echo "

Configuration Status

" echo "
"
        dgmgrl / << DGEOF
SHOW CONFIGURATION;
EXIT;
DGEOF
        echo "
" # Database Details echo "

Database Details

" sqlplus -s / as sysdba << SQLEOF SET MARKUP HTML ON SET HEADING ON SET FEEDBACK OFF SELECT name, db_unique_name, database_role, open_mode, protection_mode, protection_level, switchover_status FROM v\$database; EXIT; SQLEOF # Apply Lag echo "

Apply Lag Status

" sqlplus -s / as sysdba << SQLEOF SET MARKUP HTML ON SET HEADING ON SET FEEDBACK OFF SELECT name as database_name, value/60 as apply_lag_minutes, unit, time_computed FROM v\$dataguard_stats WHERE name = 'apply lag'; EXIT; SQLEOF # Transport Lag echo "

Transport Lag Status

" sqlplus -s / as sysdba << SQLEOF SET MARKUP HTML ON SET HEADING ON SET FEEDBACK OFF SELECT name as database_name, value/60 as transport_lag_minutes, unit, time_computed FROM v\$dataguard_stats WHERE name = 'transport lag'; EXIT; SQLEOF # Archive Destination Status echo "

Archive Destination Status

" sqlplus -s / as sysdba << SQLEOF SET MARKUP HTML ON SET HEADING ON SET FEEDBACK OFF SELECT dest_name, status, type, database_mode, recovery_mode, protection_mode, error FROM v\$archive_dest_status WHERE status != 'INACTIVE'; EXIT; SQLEOF echo "
" generate_html_footer } > "$report_file" echo "✓ Data Guard health report generated: $report_file" log_message "SUCCESS" "Data Guard health report created: $report_file" } ################################################################################ # Function: check_dg_sync_status # Description: Check if standby is in sync with primary ################################################################################ check_dg_sync_status() { local primary_db=$1 local standby_db=$2 echo "" echo "Checking synchronization between $primary_db and $standby_db" echo "=============================================================" # Check current SCN on primary echo "" echo "Primary Database Current SCN:" sqlplus -s / as sysdba << EOF SET HEADING OFF SET FEEDBACK OFF SELECT 'Current SCN: ' || CURRENT_SCN FROM v\$database; EXIT; EOF # Check apply progress on standby (would need to connect to standby) echo "" echo "For standby database $standby_db:" echo "Please verify the following on the standby:" echo " 1. MRP (Managed Recovery Process) is running" echo " 2. Apply lag is within acceptable limits" echo " 3. No apply errors in alert log" echo "" } ################################################################################ # Function: validate_dg_configuration # Description: Validate Data Guard configuration ################################################################################ validate_dg_configuration() { local primary_db=$1 log_message "INFO" "Validating Data Guard configuration for $primary_db" echo "" echo "==========================================" echo "Data Guard Configuration Validation" echo "==========================================" echo "" # Validate configuration echo "Running configuration validation..." dgmgrl / << EOF VALIDATE DATABASE VERBOSE $primary_db; EXIT; EOF echo "" # Check for configuration warnings echo "Checking for configuration warnings..." dgmgrl / << EOF SHOW CONFIGURATION LAG; EXIT; EOF echo "" log_message "INFO" "Data Guard configuration validation completed" } ################################################################################ # Function: show_dg_lag_summary # Description: Display lag summary for all standby databases ################################################################################ show_dg_lag_summary() { local primary_db=$1 echo "" echo "Data Guard Lag Summary" echo "======================" echo "" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 COLUMN name FORMAT A20 COLUMN value FORMAT A20 COLUMN unit FORMAT A10 COLUMN time_computed FORMAT A20 SELECT name, value, unit, TO_CHAR(time_computed, 'YYYY-MM-DD HH24:MI:SS') as time_computed FROM v\$dataguard_stats WHERE name IN ('apply lag', 'transport lag') ORDER BY name; EXIT; EOF echo "" } ################################################################################ # Function: check_mrp_status # Description: Check Managed Recovery Process status on standby ################################################################################ check_mrp_status() { echo "" echo "Managed Recovery Process (MRP) Status:" echo "======================================" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 SELECT process, status, thread#, sequence#, block#, blocks FROM v\$managed_standby WHERE process LIKE 'MRP%' OR process LIKE 'RFS%' ORDER BY process; EXIT; EOF echo "" } ################################################################################ # Function: check_dg_gaps # Description: Check for archive log gaps ################################################################################ check_dg_gaps() { echo "" echo "Archive Log Gap Detection:" echo "==========================" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 SELECT thread#, low_sequence#, high_sequence#, TO_CHAR(gap_time, 'YYYY-MM-DD HH24:MI:SS') as gap_time FROM v\$archive_gap; EXIT; EOF local gap_count=$(sqlplus -s / as sysdba << EOF SET HEADING OFF SET FEEDBACK OFF SET PAGESIZE 0 SELECT COUNT(*) FROM v\$archive_gap; EXIT; EOF ) gap_count=$(echo "$gap_count" | xargs) if [[ $gap_count -gt 0 ]]; then echo "" echo "⚠ WARNING: $gap_count archive log gap(s) detected!" log_message "WARN" "Archive log gaps detected: $gap_count" else echo "" echo "✓ No archive log gaps detected" log_message "INFO" "No archive log gaps" fi echo "" } ################################################################################ # Function: show_dg_statistics # Description: Show detailed Data Guard statistics ################################################################################ show_dg_statistics() { local primary_db=$1 echo "" echo "Data Guard Statistics for $primary_db" echo "======================================" echo "" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 COLUMN name FORMAT A30 COLUMN value FORMAT A20 COLUMN unit FORMAT A15 COLUMN time_computed FORMAT A20 SELECT name, value, unit, TO_CHAR(time_computed, 'YYYY-MM-DD HH24:MI:SS') as time_computed, datum_time FROM v\$dataguard_stats ORDER BY name; EXIT; EOF echo "" } ################################################################################ # Function: analyze_dg_performance # Description: Analyze Data Guard performance metrics ################################################################################ analyze_dg_performance() { local primary_db=$1 log_message "INFO" "Analyzing Data Guard performance for $primary_db" echo "" echo "Data Guard Performance Analysis" echo "===============================" echo "" # Redo generation rate echo "Redo Generation Rate (Last Hour):" echo "---------------------------------" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 SELECT TO_CHAR(first_time, 'YYYY-MM-DD HH24') as hour, COUNT(*) as log_switches, ROUND(SUM(blocks * block_size)/1024/1024, 2) as redo_mb FROM v\$archived_log WHERE first_time > SYSDATE - 1/24 GROUP BY TO_CHAR(first_time, 'YYYY-MM-DD HH24') ORDER BY hour DESC; EXIT; EOF echo "" # Network throughput echo "Network Throughput to Standby:" echo "------------------------------" sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 100 SELECT dest_name, ROUND(SUM(bytes)/1024/1024, 2) as total_mb_sent, COUNT(*) as archives_sent FROM v\$archived_log WHERE dest_id > 1 AND first_time > SYSDATE - 1 GROUP BY dest_name ORDER BY dest_name; EXIT; EOF echo "" log_message "INFO" "Data Guard performance analysis completed" } ################################################################################ # Function: quick_dg_check # Description: Quick Data Guard status check ################################################################################ quick_dg_check() { local primary_db=$1 echo "" echo "Quick Data Guard Status Check" echo "==============================" echo "" # Configuration summary dgmgrl / << EOF SHOW CONFIGURATION; EXIT; EOF echo "" # Key metrics sqlplus -s / as sysdba << EOF SET LINESIZE 200 SET PAGESIZE 50 PROMPT Database Role and Status: PROMPT ======================== SELECT name, database_role, open_mode, protection_mode, switchover_status FROM v\$database; PROMPT PROMPT Current Lag Status: PROMPT ================== SELECT name, value, unit, TO_CHAR(time_computed, 'HH24:MI:SS') as time FROM v\$dataguard_stats WHERE name IN ('apply lag', 'transport lag'); PROMPT PROMPT Archive Gaps (if any): PROMPT ===================== SELECT thread#, low_sequence#, high_sequence# FROM v\$archive_gap; EXIT; EOF echo "" } ################################################################################ # Export functions ################################################################################ export -f show_dg_status export -f check_standby_databases export -f check_apply_lag export -f check_transport_lag export -f check_dg_sync_status export -f validate_dg_configuration export -f check_mrp_status export -f check_dg_gaps export -f quick_dg_check log_message "INFO" "Data Guard health functions loaded"