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 <noreply@anthropic.com>
This commit is contained in:
cschantz
2026-02-27 20:43:32 -05:00
parent e09ffe5773
commit 6e4df51501
+30 -10
View File
@@ -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