← Terug naar kennisbank HOSTING

MySQL server has gone away — uitgelegd en opgelost

Site (of een specifieke import / plugin / cron) klapt eruit met Error: MySQL server has gone away. De fout is misleidend: in 90% van de gevallen is de MySQL-server niet weg. PHP heeft een te-grote query gestuurd (max_allowed_packet) of een verbinding te lang open laten staan (wait_timeout). Vier hoofdoorzaken, vier fixes — deze gids legt uit hoe je herkent welke je hebt en hoe je 'm verhelpt.

Het volledige error-bericht ziet er meestal zo uit:

WordPress database error MySQL server has gone away
for query SELECT * FROM wp_posts WHERE...
made by require('wp-blog-header.php'), require_once('wp-load.php'), ...

De boodschap is simpel: PHP probeerde een query naar MySQL te sturen, maar de TCP-verbinding was al verbroken. Het is bijna nóóit een echt MySQL-crash — in 95% van de gevallen is de oorzaak een van deze vier:

  1. Query te groot — over de max_allowed_packet-limiet
  2. Verbinding te lang stilgelegen — over de wait_timeout-limiet
  3. MySQL daadwerkelijk herstart of gecrasht — zeldzaam, maar het kan
  4. Persistent connection kapot gegaan — gerelateerde maar aparte oorzaak

Diagnose: welke oorzaak heb jij?

Drie vragen om te beantwoorden vóórdat je iets verandert:

1. Wanneer verschijnt de fout?

  • Tijdens een import / restore / migratie → vrijwel zeker max_allowed_packet. Een import-query met een 5 MB serialized array of een grote LONGTEXT-veld duwt over de buffer-grens.
  • Tijdens een lange cron-job die ook andere dingen doet → meestal wait_timeout. PHP staat 30+ seconden bezig zonder MySQL aan te spreken; MySQL sluit de connectie; PHP probeert daarna nog een query.
  • Willekeurig op de frontend, een paar keer per dag → vaak hoster-issue: shared MySQL onder load, of een korte herstart van de DB-server. Combineer ook met SHOW GLOBAL STATUS LIKE 'Aborted_clients'.
  • Sinds een specifieke plugin-update → de plugin doet vermoedelijk grote bulk-queries die over max_allowed_packet gaan.

2. Hoe groot is de query die faalt?

Als de error-melding de query laat zien: tel grofweg de bytes. Een query onder de 1 MB ligt zelden aan max_allowed_packet. Een query van 4–16 MB wél, want veel hosters zetten max_allowed_packet default op 1MB of 4MB.

3. Wat zegt MySQL zelf?

Als je via SSH of phpMyAdmin toegang hebt:

SHOW VARIABLES LIKE 'max_allowed_packet';
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'interactive_timeout';
SHOW GLOBAL STATUS LIKE 'Aborted_clients';
SHOW GLOBAL STATUS LIKE 'Aborted_connects';

Hoge counts in Aborted_clients = veel verbindingen die niet netjes gesloten worden — symptoom van wait_timeout issues. Lage max_allowed_packet (zoals 1M of 4M) = waarschijnlijke oorzaak van import-fouten.

Fix 1: max_allowed_packet verhogen (te grote query)

Default in MySQL is meestal 1M of 4M. Voor WordPress-imports en backups is 64M comfortabel; voor enterprise-databases kan 256M–512M nodig zijn.

Eigen MySQL / VPS

Pas my.cnf aan onder de [mysqld]-sectie:

[mysqld]
max_allowed_packet = 64M

# En herstart MySQL:
sudo systemctl restart mysql

Voor MariaDB is het equivalent. Tijdelijk testen zonder herstart kan met SET GLOBAL max_allowed_packet=67108864; — maar die instelling is verloren bij herstart.

Shared hosting

Je kunt het zelden zelf wijzigen. Mail de hoster:

"Bij imports krijg ik de melding 'MySQL server has gone away'. Naar mijn analyse zit dit aan max_allowed_packet die te laag staat. Kunnen jullie deze verhogen naar 64M voor mijn account?"

Goede hosters doen dit binnen een dag voor €0,-. Zuinige hosters wijzen je weg of weigeren — in dat geval is dat een teken dat je hosting krap is voor wat je doet.

Fix 2: wait_timeout verhogen (idle connection)

Default in MySQL is 28800 seconden (8 uur) — ruim genoeg. Maar veel shared hosters zetten 'm op 60 of 120 seconden om resources te besparen. Dat is meestal prima, behalve voor lange cron-jobs.

my.cnf:

[mysqld]
wait_timeout = 600
interactive_timeout = 600

WordPress-specifieke workaround

Liever dan wait_timeout verhogen, kun je in je code de verbinding actief houden. Tijdens een lange operatie tussen elke batch even een ping doen:

global $wpdb;

// In een lange import-loop, elke 100 items:
if ( $i % 100 === 0 ) {
    $wpdb->check_connection();  // pingt MySQL en reconnect indien nodig
    set_time_limit(60);          // reset PHP-timer ook
}

Dit is robuuster dan timeout verhogen — werkt op elke hoster zonder dat je instellingen hoeft te veranderen.

Fix 3: MySQL is daadwerkelijk gecrasht / herstart

Zeldzaam, maar gebeurt op shared hosting bij MySQL-onderhoud (meestal 's nachts). Of op een eigen VPS met te weinig geheugen waar de OOM-killer MySQL afsloot.

Diagnose:

# Op je eigen server:
sudo grep -i "out of memory" /var/log/syslog
sudo grep -i "mysqld" /var/log/syslog | tail -50
sudo systemctl status mysql

# Of in MySQL zelf:
SHOW GLOBAL STATUS LIKE 'Uptime';

Een Uptime van een paar minuten = MySQL is recent herstart. Kijk in /var/log/mysql/error.log waarom — vaak crashes na te weinig geheugen, te volle disk of een corrupt-table-recovery.

Fix 4: Persistent connections kapot gegaan

Als je code gebruik maakt van persistent MySQL connections (PDO met PDO::ATTR_PERSISTENT => true, of mysql_pconnect()), kunnen verbindingen tussen requests "ronddwalen" en kapot gaan zonder dat de applicatie het merkt. WordPress gebruikt dit niet standaard, maar custom code en sommige plugins wel.

Quick test: zet persistent connections tijdelijk uit en kijk of de fout verdwijnt. Lange-termijn: implementeer een retry-laag die op een 'gone away' opnieuw verbindt.

Hoe MySQL-fouten te debuggen tijdens een import

Database-imports zijn de #1 trigger voor deze fout. Drie technieken die ik gebruik:

1. Splits de SQL in chunks

Bij een grote mysqldump-restore (bv. 500 MB) verhoog je niet de limiet, maar split je het bestand:

# Split per X regels
split -l 50000 backup.sql backup-chunk-

# Importeer chunks één voor één
for f in backup-chunk-*; do
    mysql -u user -p database < "$f"
done

2. Gebruik --max-allowed-packet flag

mysql --max-allowed-packet=64M -u user -p database < backup.sql

# En bij dumpen:
mysqldump --max-allowed-packet=64M -u user -p database > backup.sql

3. WP-CLI met retry

Voor WordPress-imports:

wp db import backup.sql --max_allowed_packet=64M

# Of met search-replace die zware queries doet:
wp search-replace 'old' 'new' --all-tables --skip-columns=guid \
    --report-changed-only --max_allowed_packet=64M

Veelgestelde vragen

Mijn shared hoster wil max_allowed_packet niet verhogen — opties?

Drie wegen: (1) splits je import in kleinere SQL-bestanden zodat geen enkele query over de bestaande limiet gaat, (2) gebruik WP-CLI op de server met de --max_allowed_packet-flag (override per sessie), of (3) ga naar een hoster die het wel toestaat — voor €7–10 per maand krijg je hosting waar dit soort instellingen aanpasbaar is.

Verschilt deze fout op MariaDB vs. MySQL?

Nee, identiek. MariaDB is een fork van MySQL en gebruikt exact dezelfde foutmeldingen, instellingen en variabelen voor dit probleem. Alle adviezen werken op beide.

Helpt persistent connections aanzetten?

Doorgaans niet — eerder erger. Persistent connections kunnen tussen requests kapot raken zonder dat PHP het detecteert, waardoor je deze fout juist meer krijgt. WordPress en de meeste plugins werken prima met gewone (non-persistent) connections. Alleen bij hele specifieke high-traffic scenario's met goede retry-logic is persistent zinvol.

Wat is interactive_timeout vs wait_timeout?

wait_timeout geldt voor non-interactive verbindingen (PHP, scripts). interactive_timeout voor interactive (CLI mysql client). Voor PHP-WordPress is alleen wait_timeout relevant. Als beide niet gelijk staan kan dat ook verwarring geven — pas ze samen aan.

WordPress-database geeft de fout maar phpMyAdmin werkt prima — hoe?

phpMyAdmin doet kleine queries en krijgt nieuwe verbindingen per request. WordPress doet bulk-operaties tijdens uploads/imports/cron en houdt de verbinding lang open. Daarom triggert WordPress de fout en phpMyAdmin niet. De MySQL-server is voor allebei beschikbaar.

Wanneer schakel je hulp in?

De fout is meestal tame — verhoog max_allowed_packet of wait_timeout en hij is weg. Tijd voor expert-hulp als:

  • De fout terugkomt ondanks dat instellingen ruïm staan ingesteld
  • Je MySQL-error-log toont crashes (kijk in /var/log/mysql/error.log)
  • Hele tabellen onbereikbaar worden (Table is marked as crashed)
  • De fout meerdere keren per uur voorkomt op een productieve site

Vaak is dat een teken van structurele problemen: te krap geheugen op de DB-server, corrupte InnoDB-tabellen, of een hosting-laag die niet stabiel is voor jouw load.