Je errorlog, WP-CLI-uitvoer of een pluginmelding in het dashboard toont een regel als:
WordPress database error MySQL server has gone away for query [...]
Soms ziet het er anders uit: een WooCommerce CSV-import die stilletjes stopt bij rij 4.000, een migratieplugin die halverwege "database error" meldt, of een WP-Cron-taak die maar de helft van de wachtrij verwerkt. De onderliggende MySQL-clientfout is altijd dezelfde: error 2006 (CR_SERVER_GONE_ERROR).
Wat deze fout eigenlijk betekent
Error 2006 betekent dat de TCP-verbinding tussen PHP en MySQL op een gegeven moment actief was, maar dat MySQL die verbinding heeft gesloten voordat PHP de volgende query kon versturen of ontvangen. De MySQL-documentatie noemt 14 gedocumenteerde oorzaken, maar in WordPress is de trigger bijna altijd een van twee dingen: de verbinding was te lang inactief, of het querypakket was te groot.
Dit is een andere fout dan Error establishing a database connection. Die fout verschijnt als WordPress helemaal geen verbinding kan openen (verkeerde credentials, MySQL down, max_connections bereikt). "MySQL server has gone away" verschijnt nadat de verbinding al succesvol was opgezet en vervolgens tijdens hetzelfde PHP-proces werd verbroken. De database zelf draait doorgaans gewoon door.
Veelvoorkomende oorzaken, op volgorde van waarschijnlijkheid
-
wait_timeoutverlopen. MySQL sluit elke verbinding die langer inactief is danwait_timeout, wat standaard op 28.800 seconden (8 uur) staat bij zowel MySQL 8.0 als MariaDB. Dat klinkt ruim, maar shared hosts verlagen die waarde vaak naar 60–300 seconden om verbindingsslots vrij te maken. Een langlopend PHP-script dat tussen databasecalls zware berekeningen doet (beeldverwerking, XML-parsing, HTTP-calls naar externe API's) overschrijdt zo'n verlaagdewait_timeoutmakkelijk. -
Querypakket overschrijdt
max_allowed_packet. Als een enkel SQL-statement groter is danmax_allowed_packet, sluit MySQL de verbinding en retourneert error 2006. De standaardwaarde was 4 MB in MySQL 5.7 en is verhoogd naar 64 MB in MySQL 8.0. WooCommerce-productimports met grote geserialiseerdemeta_value-velden, of bulk-INSERT-statements van migratieplugins, kunnen die limiet overschrijden op oudere MySQL-versies of bij hosts die nog een conservatieve waarde hanteren. -
MySQL-server is daadwerkelijk herstart. Zeldzaam, maar het gebeurt. Een hostingprovider roteert de databaseserver, de OOM-killer beëindigt
mysqld, of een configuratiewijziging veroorzaakt een herstart. Elke verbinding van voor de herstart is daarna ongeldig. -
PHP 7.3 of ouder verbindt met MySQL 8.0. MySQL 8.0 gebruikt
caching_sha2_passwordals standaard authenticatieplugin. PHP-versies onder 7.4 ondersteunen die plugin niet. Het resultaat is error 2006 bij de allereerste query, ook al leek de verbinding succesvol. Herkenbaar doordat het meteen gebeurt, niet na een vertraging.
Diagnose voordat je iets wijzigt
Voer deze controles uit om te bepalen welke oorzaak van toepassing is. Geen van deze stappen wijzigt de database.
Controleer de huidige timeout en pakketgrootte
Maak verbinding met MySQL via de commandline of phpMyAdmin en voer uit:
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'max_allowed_packet';
Verwachte uitvoer op een standaard MySQL 8.0-installatie:
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 67108864 |
+--------------------+----------+
Als wait_timeout onder de 300 staat, of max_allowed_packet onder 16777216 (16 MB), heb je waarschijnlijk de boosdoener gevonden.
Controleer het errorlog op timing
Schakel het WordPress debug-log in als dat nog niet actief is. Open wp-config.php via de bestandsbeheerder van je hostingpanel (of via SFTP) en voeg deze regels toe (of controleer of ze er al staan):
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true); // schrijft naar wp-content/debug.log
define('WP_DEBUG_DISPLAY', false);
Voer de falende bewerking opnieuw uit en bekijk wp-content/debug.log. Het WordPress debug-logartikel beschrijft deze configuratie uitgebreider. Als de fout verschijnt na meerdere minuten verwerking, is wait_timeout de oorzaak. Verschijnt die bij de eerste grote batch-insert, dan is max_allowed_packet waarschijnlijker.
Controleer PHP- en MySQL-versies
Ga in wp-admin naar Gereedschap > Website-gezondheid > Info > Server. Zowel de PHP-versie als de databaseserverversie staan daar vermeld. Je kunt ook de PHP-versiekiezer in je hostingpanel bekijken, en phpMyAdmin toont de MySQL- of MariaDB-versie op het startscherm.
Als je SSH-toegang hebt:
php -v
mysql --version
Als je PHP 7.3 of lager ziet in combinatie met MySQL 8.0, is de authenticatieplugin-mismatch de meest waarschijnlijke oorzaak.
Fix 1: verhoog max_allowed_packet voor grote queries
Deze fix richt zich op oorzaak 2: het query- of datapakket is te groot voor de huidige limiet.
Veel hostingpanelen bieden een MySQL-configuratiescherm of een supportoptie om max_allowed_packet te verhogen. Kijk eerst in de database-instellingen van je hostingpanel. Als je host die optie niet biedt, kun je de waarde per sessie instellen via een must-use plugin. Maak het bestand wp-content/mu-plugins/raise-packet-size.php aan via de bestandsbeheerder van je hostingpanel of een SFTP-client:
<?php
// Verhoog max_allowed_packet voor alleen deze MySQL-sessie.
// Veilig om bij elk request uit te voeren; de SET raakt alleen de huidige verbinding.
global $wpdb;
$wpdb->query("SET SESSION max_allowed_packet = 128 * 1024 * 1024");
Als je SSH-toegang hebt en de MySQL-serverconfiguratie kunt bewerken, voeg dan onder de [mysqld]-sectie van my.cnf (of my.ini op Windows) toe:
[mysqld]
max_allowed_packet = 128M
Herstart daarna MySQL:
# systemd op Debian/Ubuntu
sudo systemctl restart mysql
# of MariaDB
sudo systemctl restart mariadb
Je weet dat het werkt als de import of migratie volledig doorloopt zonder de "gone away"-fout en SHOW VARIABLES LIKE 'max_allowed_packet' in phpMyAdmin de nieuwe waarde toont.
Fix 2: verhoog wait_timeout voor langlopende scripts
Deze fix richt zich op oorzaak 1: de verbinding is te lang inactief tussen queries.
Sommige hostingpanelen laten je wait_timeout aanpassen via database-instellingen of een supportverzoek. Als dat niet beschikbaar is, kun je het per sessie instellen vanuit WordPress. Maak een must-use plugin aan op wp-content/mu-plugins/raise-wait-timeout.php via de bestandsbeheerder van je hostingpanel of SFTP:
<?php
// Verhoog wait_timeout voor alleen deze MySQL-sessie.
global $wpdb;
$wpdb->query("SET SESSION wait_timeout = 3600");
Je kunt dit ook als eenmalige query uitvoeren in phpMyAdmin voordat je een grote import start:
SET SESSION wait_timeout = 3600;
WP-CLI-alternatief:
wp db query "SET SESSION wait_timeout = 3600"
Als je SSH-toegang hebt en de MySQL-serverconfiguratie kunt bewerken, voeg toe aan my.cnf onder [mysqld]:
[mysqld]
wait_timeout = 3600
Houd de waarde redelijk. wait_timeout op 86400 (24 uur) zetten op een server met 151 max_connections betekent dat 151 inactieve verbindingen een hele dag kunnen blijven bestaan, terwijl ze verbindingsslots bezetten die actieve requests nodig hebben. Een waarde tussen 1.800 en 3.600 seconden dekt de meeste langlopende WordPress-taken af zonder verbindingen te hoarden.
Je weet dat het werkt als de langlopende taak volledig doorloopt zonder error 2006. Duurt de taak langer dan een uur, dan is het ook de moeite waard om die op te splitsen in kleinere batches (zie het preventiegedeelte hieronder).
Fix 3: los de PHP/MySQL-authenticatiemismatch op
Deze fix richt zich op oorzaak 4: PHP < 7.4 verbindt met MySQL 8.0 via caching_sha2_password.
De juiste oplossing is PHP upgraden naar minimaal 7.4, dat native ondersteuning voor caching_sha2_password toevoegt. De meeste hostingpanelen hebben een PHP-versiekiezer waarmee je dit met een enkele klik regelt. PHP 7.3 bereikte end-of-life in december 2021 en ontvangt geen beveiligingspatches meer.
Als PHP upgraden niet meteen mogelijk is, kun je de authenticatieplugin van de MySQL-gebruiker terugzetten naar mysql_native_password:
ALTER USER 'wp_user'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'jouw-wachtwoord-hier';
FLUSH PRIVILEGES;
Dit is een noodoplossing. mysql_native_password is deprecated in MySQL 8.0 en kan in een toekomstige versie worden verwijderd.
Je weet dat het werkt als error 2006 niet meer verschijnt bij de eerste query en de verbinding in stand blijft voor volgende queries.
Hoe WordPress deze fout intern afhandelt
Sinds WordPress 3.9 detecteert de wpdb::check_connection()-methode error 2006, probeert tot 5 keer opnieuw te verbinden met intervallen van 1 seconde, en herhaalt de mislukte query eenmaal. Dat betekent dat kortstondige onderbrekingen (een MySQL-herstart die 2–3 seconden duurt) vaak ongemerkt worden opgevangen.
Het herverbindingsbudget is beperkt: 5 pogingen, elk 1 seconde apart. Als MySQL na 5 seconden nog steeds niet bereikbaar is, geeft WordPress het op en retourneert false (tijdens front-endrendering na template_redirect) of roept dead_db() aan en stopt het proces. Voor achtergrondtaken als WP-Cron of WP-CLI werkt de reconnectlogica op dezelfde manier, maar de taak zelf hervat niet vanaf het punt van falen. De halfvoltooide import blijft halfvoltooid.
Wanneer escaleren
Als het verhogen van wait_timeout en max_allowed_packet de fout niet oplost, kan de oorzaak op infrastructuurniveau liggen (firewall die inactieve TCP-verbindingen dropt, MySQL-proces dat crasht, OOM-killer). Verzamel het volgende voordat je een ticket opent bij je host of bij mij:
- De exacte foutregel uit
wp-content/debug.logof het PHP-errorlog - Uitvoer van
SHOW VARIABLES LIKE 'wait_timeout'enSHOW VARIABLES LIKE 'max_allowed_packet' - Je WordPress-, PHP- en MySQL/MariaDB-versies
- De bewerking die de fout triggert (import, migratie, WP-CLI-commando, cronjob)
- Hoe lang de bewerking draait voor die faalt (30 seconden? 10 minuten? 2 uur?)
- Of de fout bij elke poging optreedt of wisselend
- De laatste 50 regels van
/var/log/mysql/error.log(of het equivalent in je hostingpanel)
Deze informatie is het verschil tussen een supportgesprek met giswerk en een supportgesprek met een oplossing in de eerste reactie.
Herhaling voorkomen
- Splits grote bewerkingen op in batches. Een WooCommerce-import van 50.000 producten hoort in stukken van 500–1.000 rijen te draaien, met expliciete commits tussen batches. De meeste importplugins (WP All Import, de ingebouwde WooCommerce-importeur) hebben een batchgrootte-instelling. Gebruik die.
- Vermijd inactieve gaten in langlopende scripts. Als je script HTTP-calls maakt, afbeeldingen verwerkt of wacht op externe API's tussen databasequeries, kan de verbinding een timeout krijgen. Roep
$wpdb->check_connection()aan voor de volgende query na elke lange niet-databaseoperatie, of stel een ruime sessie-wait_timeoutin. - Zet
max_allowed_packetboven 64 MB op MySQL 5.7. De standaard van 4 MB op MySQL 5.7 is te klein voor de meeste WordPress-sites met WooCommerce of custom post types die geserialiseerde data opslaan. MySQL 8.0 staat standaard op 64 MB, maar als je nog op 5.7 zit, stel het dan expliciet in. - Monitor
Aborted_clients. De MySQL-statusvariabeleAborted_clientsloopt op bij elke verbinding die wordt gesloten doordat de client die niet netjes afsloot (dat omvat ook timeout-sluitingen). Een stijgend aantal vertelt je dat het probleem terugkeert, ook als niemand meekijkt.
SHOW GLOBAL STATUS LIKE 'Aborted_clients';
Als je een fout ziet die maximum execution time exceeded meldt, is dat een ander probleem: PHP zelf doodt het script, niet MySQL die de verbinding sluit. De twee verschijnen vaak tijdens hetzelfde soort langlopende taken, maar de oplossingen zijn totaal anders.