XAMPP su Windows: risolvere “MySQL shutdown unexpectedly” e riparare una tabella MariaDB danneggiata

Sintomo

Avviando MySQL/MariaDB dal pannello di controllo di XAMPP su Windows, può capitare di incontrare questo messaggio:

Error: MySQL shutdown unexpectedly.
This may be due to a blocked port, missing dependencies,
improper privileges, a crash, or a shutdown by another method.

Il messaggio è piuttosto generico: ci informa che il server non riesce ad avviarsi, ma non spiega perché.

Nel mio caso, il problema riguardava MariaDB 10.4.32, distribuito con XAMPP, e una tabella di sistema danneggiata: mysql.db.

Vediamo come sono arrivato alla diagnosi e come ho risolto il problema, senza reinstallare XAMPP e senza sostituire l’intera directory dei database.

Diagnosi

Verificare che la porta 3306 sia libera

La prima ipotesi è che un altro processo stia già utilizzando la porta TCP 3306, normalmente impiegata da MySQL e MariaDB.

Apriamo PowerShell ed eseguiamo:

netstat -ano | findstr :3306

Se compare una riga con lo stato LISTENING, possiamo identificare il processo attraverso il PID:

tasklist /FI "PID eq 1234"

Nel mio caso il comando netstat non restituiva alcun risultato: la porta era libera.

Era quindi necessario cercare altrove.

Esaminare il log di MariaDB

Il log si trova normalmente in:

C:\xampp\mysql\data\mysql_error.log

Il mio conteneva un messaggio decisamente preoccupante:

InnoDB: Assertion failure in file
storage\innobase\os\os0file.cc line 6132

InnoDB: Failing assertion: slot

Seguiva un’indicazione relativa a una possibile corruzione del tablespace InnoDB.

Questo messaggio, però, non era sufficiente a individuare con certezza il problema.

Tentare l’avvio in modalità di recupero

Prima di intervenire sui file è indispensabile arrestare MariaDB ed effettuare una copia completa della directory:

C:\xampp\mysql\data

Possiamo verificare che il processo sia fermo con:

Get-Process mysqld -ErrorAction SilentlyContinue

Per tentare un avvio diagnostico, apriamo:

C:\xampp\mysql\bin\my.ini

Nella sezione [mysqld] aggiungiamo:

innodb_force_recovery=1

Questo parametro attiva una modalità di recupero di InnoDB. Non ripara automaticamente i database e non deve essere lasciato attivo durante il normale utilizzo.

Nel mio caso, il server continuava a non avviarsi, ma il nuovo tentativo ha permesso di proseguire con la diagnosi.

Avviare MariaDB direttamente dalla console

Il pannello XAMPP non mostra sempre tutte le informazioni necessarie.

È molto più utile avviare direttamente il server da PowerShell:

cd C:\xampp\mysql\bin

.\mysqld.exe --defaults-file="C:\xampp\mysql\bin\my.ini" --console

Questa volta è comparso l’errore che cercavo:

[ERROR] mysqld.exe: Table '.\mysql\db' is marked as crashed
and last (automatic?) repair failed

[ERROR] Fatal error: Can't open and lock privilege tables

Finalmente una diagnosi precisa: la tabella di sistema mysql.db era danneggiata.

Questa tabella contiene informazioni sui privilegi di accesso ai database.

Non bisogna confonderla con un database applicativo: appartiene allo schema di sistema mysql, utilizzato internamente da MariaDB.

Verificare l’integrità della tabella con aria_chk

In MariaDB 10.4 la tabella mysql.db utilizza normalmente il motore di memorizzazione Aria.

I file coinvolti sono:

C:\xampp\mysql\data\mysql\db.frm
C:\xampp\mysql\data\mysql\db.MAD
C:\xampp\mysql\data\mysql\db.MAI

Il file .frm descrive la struttura della tabella, .MAD contiene i dati e .MAI contiene gli indici e le informazioni necessarie alla loro gestione.

Con MariaDB fermo, possiamo verificarne l’integrità:

C:\xampp\mysql\bin\aria_chk.exe --check --datadir="C:\xampp\mysql\data" "C:\xampp\mysql\data\mysql\db.MAI"

Nel mio caso il risultato era:

Index is corrupted

doesn't have a correct index definition.
You need to recreate it before you can do a repair

Non si trattava dunque di un semplice problema di connessione.

Recuperare la tabella dalla copia originale di XAMPP

XAMPP distribuisce normalmente una copia iniziale delle tabelle di sistema nella directory:

C:\xampp\mysql\backup\mysql

Prima di utilizzarla, ho verificato che fosse integra:

C:\xampp\mysql\bin\aria_chk.exe --check --datadir="C:\xampp\mysql\data" "C:\xampp\mysql\backup\mysql\db.MAI"

Il controllo è terminato senza errori.

A questo punto, con MariaDB fermo e dopo aver effettuato un backup completo, ho ripristinato i tre file della tabella:

Copy-Item "C:\xampp\mysql\backup\mysql\db.frm" `
          "C:\xampp\mysql\data\mysql\db.frm" -Force

Copy-Item "C:\xampp\mysql\backup\mysql\db.MAD" `
          "C:\xampp\mysql\data\mysql\db.MAD" -Force

Copy-Item "C:\xampp\mysql\backup\mysql\db.MAI" `
          "C:\xampp\mysql\data\mysql\db.MAI" -Force

Attenzione: questa soluzione è appropriata soltanto quando la copia di sistema è compatibile con la versione installata e la tabella interessata è stata identificata con precisione.

Sostituire mysql.db con la versione originale può far perdere le autorizzazioni personalizzate contenute nella tabella. È quindi opportuno verificare successivamente i privilegi degli utenti.

Non bisogna invece sostituire indiscriminatamente l’intera directory data, né cancellare file InnoDB come ibdata1.

Verificare che MariaDB sia tornato operativo

Dopo il ripristino ho avviato nuovamente il server:

C:\xampp\mysql\bin\mysqld.exe --defaults-file="C:\xampp\mysql\bin\my.ini" --console

Questa volta il processo è rimasto in esecuzione.

Da una seconda finestra PowerShell ho verificato la connessione:

C:\xampp\mysql\bin\mysqladmin.exe -u root ping

Risultato:

mysqld is alive

MariaDB era finalmente tornato a rispondere!

Per controllare anche l’accesso ai database:

C:\xampp\mysql\bin\mysql.exe -u root -e "SHOW DATABASES;"

Per arrestare ordinatamente il server:

C:\xampp\mysql\bin\mysqladmin.exe -u root shutdown

Se l’utente richiede una password, occorre utilizzare l’opzione -p.

Tornare alla modalità di funzionamento normale

La modalità innodb_force_recovery=1 era stata utilizzata esclusivamente per la diagnosi.

Prima di tornare a utilizzare normalmente XAMPP, bisogna arrestare MariaDB, rimuovere o commentare il parametro nel file my.ini:

# innodb_force_recovery=1

e verificare che il server si avvii correttamente anche senza la modalità di recupero:

XAMPP MariaDB
XAMPP MariaDB

Il riavvio stavolta ha funzionato.

È inoltre consigliabile controllare le tabelle applicative, i privilegi degli utenti ed effettuare un’esportazione SQL dei database.

Nel caso descritto, il ripristino della tabella Aria ha permesso di recuperare l’avvio in modalità diagnostica. L’eventuale problema InnoDB segnalato inizialmente richiede una verifica separata con la modalità di recupero disattivata.

Conclusioni

Il messaggio MySQL shutdown unexpectedly non identifica una causa precisa: è soltanto il sintomo di un arresto del server.

In questo caso, il percorso diagnostico è stato:

  1. Verifica della porta TCP 3306.
  2. Analisi del log di MariaDB.
  3. Tentativo di avvio in modalità di recupero.
  4. Avvio diretto con mysqld.exe --console.
  5. Identificazione della tabella mysql.db danneggiata.
  6. Verifica dell’integrità con aria_chk.
  7. Ripristino mirato della tabella da una copia integra.
  8. Verifica della risposta del server.

La lezione più importante è che prima di reinstallare XAMPP o cancellare i file dei database conviene leggere attentamente i log e individuare il componente effettivamente danneggiato.

Spesso un intervento mirato è sufficiente a recuperare un’installazione che sembrava compromessa.

Riferimenti

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.