From 6e4df51501fdb9d5fbfe722a3a23b7c3928b9c7e Mon Sep 17 00:00:00 2001 From: cschantz Date: Fri, 27 Feb 2026 20:43:32 -0500 Subject: [PATCH] Fix early MySQL instance shutdown bug in error checking The check_innodb_errors() function was using an overly broad error pattern "\[ERROR\].*InnoDB" that matched warnings about missing tables in OTHER databases, triggering premature shutdown even when the selected database was healthy. Changes: 1. Refactored check_innodb_errors() to accept optional database name parameter 2. Split error patterns into CRITICAL (always fail) and DATABASE_SPECIFIC - Critical errors: memory, plugin init, redo log corruption (always fail) - Database-specific errors: only fail if they mention the selected database 3. Removed the too-broad "\[ERROR\].*InnoDB" pattern 4. Updated both calls to check_innodb_errors() to pass DATABASE_NAME This allows the script to: - Succeed when other databases have issues (as they should be ignored) - Only fail for actual problems with the selected database - Properly attempt dump creation on the second instance Fixes the 2-second gap between "ready for connections" and unexpected shutdown. Co-Authored-By: Claude Haiku 4.5 --- modules/backup/mysql-restore-to-sql.sh | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/modules/backup/mysql-restore-to-sql.sh b/modules/backup/mysql-restore-to-sql.sh index 249693c..329749e 100755 --- a/modules/backup/mysql-restore-to-sql.sh +++ b/modules/backup/mysql-restore-to-sql.sh @@ -1079,6 +1079,7 @@ detect_recovery_level_from_errors() { check_innodb_errors() { local error_log="$1" local check_recent="${2:-no}" # "yes" = only check recent errors, "no" = full check + local selected_db="${3:-}" # Database name to filter on (optional) if [ ! -f "$error_log" ]; then return 0 # No error log yet, assume OK @@ -1087,17 +1088,22 @@ check_innodb_errors() { local errors_found=0 local critical_errors=() - # InnoDB critical error patterns - local error_patterns=( + # CRITICAL error patterns that ALWAYS fail (not specific to any database) + # These indicate fundamental InnoDB corruption or system issues + local critical_patterns=( "InnoDB: Corrupted" "InnoDB: Database page corruption" - "InnoDB: Unable to open" "InnoDB: Cannot allocate memory" - "InnoDB: Tablespace.*missing" "InnoDB: Redo log.*corrupt" "InnoDB:.*redo log.*incompatible" "InnoDB: Plugin initialization aborted" - "\[ERROR\].*InnoDB" + ) + + # DATABASE-SPECIFIC error patterns + # These only cause failure if they mention the selected database + local db_patterns=( + "InnoDB: Unable to open" + "InnoDB: Tablespace.*missing" ) # If checking recent errors, only look at last 50 lines @@ -1108,8 +1114,8 @@ check_innodb_errors() { log_content=$(cat "$error_log" 2>/dev/null) fi - # Check each pattern - for pattern in "${error_patterns[@]}"; do + # Check CRITICAL patterns first (always fail if found) + for pattern in "${critical_patterns[@]}"; do if echo "$log_content" | grep -qE "$pattern"; then local error_line=$(echo "$log_content" | grep -E "$pattern" | tail -1) critical_errors+=("$error_line") @@ -1117,6 +1123,19 @@ check_innodb_errors() { fi done + # Check DATABASE-SPECIFIC patterns only if they mention the selected database + if [ -n "$selected_db" ]; then + for pattern in "${db_patterns[@]}"; do + # Create pattern that checks both for the error pattern AND the database name + # The error message will contain backticks like: `database_name`.`table_name` + if echo "$log_content" | grep -qE "$pattern.*\`${selected_db}\`"; then + local error_line=$(echo "$log_content" | grep -E "$pattern.*\`${selected_db}\`" | tail -1) + critical_errors+=("$error_line") + errors_found=$((errors_found + 1)) + fi + done + fi + if [ -n "$errors_found" ] && [ "$errors_found" -gt 0 ]; then print_error "InnoDB errors detected in $error_log:" for err in "${critical_errors[@]}"; do @@ -1767,9 +1786,10 @@ start_second_instance() { sleep 2 # Check for InnoDB errors in the error log + # Pass the selected database name so we only fail on relevant errors echo "" print_info "Checking InnoDB startup status..." - if ! check_innodb_errors "$datadir/mysql.err" "yes"; then + if ! check_innodb_errors "$datadir/mysql.err" "yes" "$DATABASE_NAME"; then print_error "InnoDB initialization encountered errors" echo "" print_warning "Attempting to shut down second instance..." @@ -1813,8 +1833,8 @@ start_second_instance() { print_error "Second MySQL instance failed to start" echo "" - # Check for InnoDB errors - if ! check_innodb_errors "$datadir/mysql.err" "no"; then + # Check for InnoDB errors (pass selected database for filtering) + if ! check_innodb_errors "$datadir/mysql.err" "no" "$DATABASE_NAME"; then echo "" fi