Error establishing a database connection WordPress is die witte pagina met één regel tekst waar iedere webshop-eigenaar ’s ochtends bang voor is. Vorige week woensdag: telefoontje van een klant met een B2B-webshop in Hulst. “Ik heb net op mijn iPad geopend en er staat alleen die database-error. Bestellingen die binnenkomen zie ik niet meer.”
Geen paniek nodig. In tachtig procent van de gevallen ligt het aan één van vier oorzaken. Die vind je terug via een gestructureerde diagnose.
In dit stuk lees je precies hoe ik dat doe. Je ziet welke commando’s ik in welke volgorde draai, en hoe je hetzelfde aanpakt in cPanel, Plesk, DirectAdmin, Hostinger en op een managed VPS via SSH. Reken op 30 tot 90 minuten van eerste melding tot volledige fix.

Error establishing a database connection WordPress: wat gebeurt er onder de motorkap
Voor je op reset-knoppen begint te drukken is het handig om te begrijpen wat WordPress feitelijk probeert. Bij elke pagina-request doet WordPress via PHP een mysqli_connect() naar de host, gebruikersnaam en database-naam die in wp-config.php staan. Slaagt die connectie niet, dan rendert WordPress niks: geen theme, geen plugins, alleen de fatale foutmelding. Er zijn vier hoofdklassen problemen die ik in mijn praktijk zie:
1. Credentials kloppen niet meer. Meest voorkomend na een migratie of hosting-wissel. De site draait op nieuwe hosting maar wp-config.php verwijst nog naar de oude DB_USER of DB_HOST. Ook: hosting heeft het MySQL-wachtwoord automatisch geroteerd (Cloudways en Kinsta doen dit periodiek) en wp-config.php is niet meegegaan.
2. Database-server is over z’n limiet. De MySQL-daemon draait, maar accepteert geen nieuwe verbindingen omdat max_user_connections of max_connections bereikt is. Klassiek bij verkeerspiek, een spamgolf naar wp-login.php, of een backup-taak die parallel aan een cron-job draait. Ook shared hosting geeft dit vaak: de daemon deelt resources met andere klanten en jouw pool zit vol.
3. Tabel(len) corrupt. Een wp_options– of wp_posts-tabel raakt gecorrumpeerd, meestal na een crash, stroomstoring in het datacenter, of een harde restart tijdens een schrijfactie. WordPress verbindt wel met de database maar krijgt bij het lezen van corrupte tabellen een fout die als connection-error rendert.
4. wp-config.php zelf beschadigd. Bestand raakt corrupt na een half-mislukte edit via FTP, of iemand heeft per ongeluk quotes verkeerd geëscaped. Vaak samen met een 500-fout in het error-log.
Kinsta heeft een uitgebreide referentiegids over deze fout die de wereldwijde support-tickets van hun engineers samenvat, en die de klassen die ik hierboven noem netjes bevestigt.
Stap 1: Persistent of intermitterend?
Dit is de belangrijkste vraag voordat je iets doet. Refresh de pagina drie keer met 30 seconden ertussen.
Blijft de fout elke keer verschijnen, dan zit je in klasse 1, 3 of 4 (credentials, corrupte tabel, of corrupte config). Ga naar stap 2.
Verschijnt de fout soms wel, soms niet, dan is het klasse 2 (limiet-issue). De DB-daemon werkt normaal, maar knijpt af bij piekbelasting. Ga direct naar stap 7 (resources).
Check ook je error-log. Bij cPanel: File Manager → error_log in de site-root. Bij Plesk: Domains → jouwsite.nl → Logs. Op een managed VPS via SSH.
# Live tail van het error-log
tail -f /home/username/logs/jouwsite.nl.error.logZoek regels als Access denied for user, Can't connect to MySQL server, Too many connections, of Table is marked as crashed. Elke regel wijst richting één van de vier klassen.
Stap 2: wp-config.php verifiëren
Open wp-config.php in de site-root via je File Manager of via SSH. Doe dit niet via de wp-admin theme editor, want die werkt sowieso niet als je de database-error hebt.
De vier variabelen die ertoe doen.
define('DB_NAME', 'jouwsite_wp');
define('DB_USER', 'jouwsite_admin');
define('DB_PASSWORD', 'JouwWachtwoordHier');
define('DB_HOST', 'localhost');Controleer alle vier tegen de daadwerkelijke waarden in je hostingpaneel (zie stap 4B). Let vooral op.
- Overschrijvende quotes.
define('DB_PASSWORD', 'w@chtwoord's')breekt door de single-quote in het wachtwoord. Fix: dubbele quotes gebruiken:define('DB_PASSWORD', "w@chtwoord's");. - DB_HOST-waarde.
localhostwerkt niet overal, zie stap 3. - Onzichtbare BOM-karakters aan het begin van het bestand. Als je
wp-config.phpin Windows Notepad hebt geopend en opgeslagen, kan er een byte-order-mark aan het begin staan die PHP crasht. Open opnieuw met Notepad++, VS Code of via terminal en sla op als UTF-8 zonder BOM.
Zie de officiële wp-config.php reference voor de exhaustieve lijst van constanten.
Stap 3: DB_HOST varianten testen
localhost is de default en werkt op de meeste shared hosting, maar niet altijd. In mijn praktijk kom ik regelmatig deze varianten tegen.
// Default, werkt op circa 90% van shared hosting
define('DB_HOST', 'localhost');
// Als 'localhost' faalt: IP forceert TCP in plaats van socket
define('DB_HOST', '127.0.0.1');
// Sommige Nederlandse hosters (o.a. TransIP legacy, Hostnet legacy)
define('DB_HOST', 'mysql.jouwdomein.nl');
// Niet-standaard poort
define('DB_HOST', 'localhost:3307');
// Expliciete socket (na MariaDB reinstall of custom compile)
define('DB_HOST', 'localhost:/var/lib/mysql/mysql.sock');
define('DB_HOST', 'localhost:/var/run/mysqld/mysqld.sock');
// Managed database (Kinsta, Cloudways, DigitalOcean managed DB)
define('DB_HOST', 'private-database-abc123.b.db.ondigitalocean.com:25060');Test één variant tegelijk. Sla wp-config.php op, refresh de site. Ander resultaat? Weer terug naar de vorige waarde en probeer de volgende.
De reden dat 127.0.0.1 soms werkt en localhost niet: MySQL en MariaDB behandelen localhost als een instructie om te verbinden via unix-socket. Op systemen waar de socket op een niet-standaard pad staat (of niet bestaat), faalt dat. 127.0.0.1 forceert TCP over poort 3306 en omzeilt het socket-probleem.
Stap 4: Test-script met mysqli connect
Voordat je uren verspilt aan wp-config-varianten, isoleer je de vraag: kan PHP zelf überhaupt verbinden met de database met de credentials die je hebt? Maak een test-bestand db-test.php in de site-root.
<?php
$host = 'localhost';
$user = 'jouwsite_admin';
$password = 'JouwWachtwoordHier';
$database = 'jouwsite_wp';
$conn = new mysqli($host, $user, $password, $database);
if ($conn->connect_error) {
die('Connection failed: ' . $conn->connect_error);
}
echo 'Connected: server version ' . $conn->server_info;
$conn->close();Open https://jouwsite.nl/db-test.php. Drie mogelijke uitkomsten.
- “Connected: server version 8.0.35” (of MariaDB 10.11+). Credentials kloppen. De fout zit in WordPress zelf, meestal een corrupte tabel. Ga naar stap 5.
- “Connection failed: Access denied for user”. Credentials zijn fout. Ga naar stap 4B: credentials resetten per hostingpaneel.
- “Connection failed: Can’t connect to MySQL server on ‘localhost'”. De daemon draait niet of DB_HOST-waarde is fout. Contact hosting-support.
Verwijder db-test.php direct na de test. Wachtwoorden in plaintext op een publiek bestand is een security-risico.
Stap 4B: Credentials resetten per hostingpaneel
DirectAdmin (Antagonist, Vimexx, mijn.host)
- Login → MySQL Databases.
- Onder “Current Users”: klik “Change Password” naast je DB-user.
- Genereer wachtwoord (kopieer direct), submit.
- Update
wp-config.phpmet het nieuwe wachtwoord.
Plesk (Argeweb, en op VPS bij TransIP en Combell)
- Domains → jouwsite.nl → Databases.
- Klik de user aan onder je database → User settings.
- “New password” invullen → OK.
- Update
wp-config.php.
cPanel (o.a. Neostrada)
- Login → MySQL Management.
- Klik
_databasenaamaan. - “Modify User” → nieuw wachtwoord invoeren → Save.
Hostinger hPanel
- Dashboard → jouwsite.nl → Databases → Management.
- Onder “List of Current MySQL Databases”: klik de drie stipjes → Change password.
- Kopieer het nieuwe wachtwoord.
Cloudways Platform
- Application → Access Details → onder “MySQL Access”.
- DB-name, DB-user en DB-password staan hier.
- Password rotatie: Applications → Settings → Reset MySQL Password.
- Update
wp-config.php(kan meestal ook via Application → SSH terminal).
RunCloud, ServerAvatar, GridPane (managed VPS)
- RunCloud: Server → Databases → Users → klik user → Reset password.
- GridPane: Sites → jouwsite → Site Info → onder “MySQL Details”.
- ServerAvatar: Application → Database → onder “Manage users”.
SSH-direct (root of MySQL-admin)
Werkt op elke VPS waar je root of mysql-admin bent.
# Login als root of via socket auth
mysql -u root -p
# In de MySQL-prompt:
ALTER USER 'jouwsite_admin'@'localhost' IDENTIFIED BY 'NieuwWachtwoord';
FLUSH PRIVILEGES;
EXIT;Voor MariaDB ouder dan 10.2 gebruikte je SET PASSWORD FOR ... = PASSWORD('...'). Sinds MariaDB 10.2 en MySQL 8 is ALTER USER de canonieke syntax.

Stap 5: Database repair via WP_ALLOW_REPAIR
Slaagt de test uit stap 4 maar blijft de fout? Dan is er waarschijnlijk een tabel corrupt. WordPress heeft een ingebouwde repair-tool die je activeert via wp-config.php.
Voeg deze regel toe vlak boven de comment /* That's all, stop editing! Happy publishing. */.
define('WP_ALLOW_REPAIR', true);Sla op, ga naar https://jouwsite.nl/wp-admin/maint/repair.php. Twee knoppen.
- Repair Database: draait
REPAIR TABLEop alle WordPress-tabellen. - Repair and Optimize Database: repair plus
OPTIMIZE TABLE(defragmenteert).
Kies de tweede optie. De tool loopt door alle tabellen en rapporteert per tabel: “OK”, “repaired” of “not fixable”. Duur: 1 tot 5 minuten voor een standaard site, tot 20+ minuten voor een grote WooCommerce-shop met 50.000+ orders.
Belangrijk voor security: verwijder de WP_ALLOW_REPAIR-regel direct na gebruik. De repair-URL is niet-geauthenticeerd, dus zolang de constante true is kan iedereen die de URL kent een repair triggeren. Zie de officiële wp db repair documentatie voor CLI-alternatieven zonder deze exposure.
Stap 6: WP-CLI en mysqlcheck voor SSH-users
Heb je SSH-toegang, dan zijn WP-CLI en mysqlcheck sneller en veiliger dan de web-interface.
WP-CLI database diagnostics
# Ga naar site root
cd /home/username/webapps/jouwsite/public_html
# Check tabel-status (equivalent van CHECK TABLE op alles)
wp db check
# Repair alle tabellen (equivalent van repair.php maar authenticated)
wp db repair
# Optimize (defrag) alle tabellen
wp db optimize
# Database-grootte per tabel, om te zien waar bloat zit
wp db size --format=table --tables
# Live connectie-teller, is de pool vol?
wp db query "SHOW GLOBAL STATUS LIKE 'Threads_connected';"
# Actieve queries, welke query blokkeert de rest?
wp db query "SHOW PROCESSLIST;"De WP-CLI db-command reference documenteert alle subcommands. Voor developers die alle drie de operaties in één keer willen.
wp db check && wp db repair && wp db optimizemysqlcheck als WP-CLI niet beschikbaar is
Op sommige shared hostings ontbreekt WP-CLI. Dan direct via mysqlcheck.
# Check alle tabellen in één database
mysqlcheck -u jouwsite_admin -p --check jouwsite_wp
# Check plus auto-repair
mysqlcheck -u jouwsite_admin -p --auto-repair --check jouwsite_wp
# Alle databases die deze user mag benaderen
mysqlcheck -u jouwsite_admin -p --all-databases --check --auto-repair
# Repair plus optimize gecombineerd (root-user only)
mysqlcheck -u root -p --auto-repair -c -o --all-databasesDe opties -c (check), -r (repair), -a (analyze) en -o (optimize) zijn onderling exclusief per run, maar je kunt ze wel combineren als -c -o (check gevolgd door optimize). Zie de MySQL 8.4 mysqlcheck reference en de MariaDB mariadb-check documentatie voor volledige syntax.
Waarschuwing: REPAIR TABLE werkt alleen op MyISAM- en Aria-tabellen. Voor InnoDB (default in WordPress sinds core 3.5) doet het niks. InnoDB-corruptie fix je via innodb_force_recovery in my.cnf, en dat is werk voor een DBA, geen zelfhulp.
Stap 7: Resource-check bij intermitterende fouten
Was jouw diagnose in stap 1 dat de fout soms komt en gaat? Dan zit je in max_user_connections– of resource-territorium.
Query je huidige connectie-pool.
-- Via WP-CLI (wp db query) of phpMyAdmin
SHOW VARIABLES LIKE 'max_user_connections';
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';Als Max_used_connections gelijk is aan of dicht bij max_user_connections ligt, zit je aan het plafond. Typische shared-hosting-limieten die ik in de praktijk zie.
- HostGator: 25 gelijktijdige verbindingen per cPanel.
- InMotion: 20 gelijktijdig.
- Antagonist, Vimexx, Hostnet (Nederland): meestal 20 tot 30, afhankelijk van pakket.
- Combell shared: circa 30.
- Kinsta en Cloudways managed: 100+, afhankelijk van plan.
Zit je aan het plafond, dan zijn er drie hefbomen:
1. Object cache activeren. Redis of Memcached vermindert DB-queries drastisch. Kinsta en Cloudways bieden Redis met 1-klik, bij shared hosting via een plugin als Redis Object Cache (mits hosting Redis heeft).
2. Autoload cleanup. Grote transients en gestrande option-rijen bloaten wp_options. Query voor de zondaars.
SELECT option_name, LENGTH(option_value) AS size
FROM wp_options
WHERE autoload = 'yes'
ORDER BY size DESC
LIMIT 20;Rijen boven 1 MB die niet kritiek zijn (oude session data, verlopen transients, verlaten plugins): UPDATE wp_options SET autoload = 'no' WHERE option_name = '...';
3. Upgrade pakket of naar managed hosting. Als niks anders werkt en je consequent aan het plafond zit bij normaal verkeer, is je site z’n huidige pakket ontgroeid.
Contact hosting-support met concrete cijfers uit je diagnose: “Max_used_connections is consistent 20 op piek, wp_options is 240 MB waarvan 180 MB autoload. Kan mijn limiet naar 50 verhoogd of moet ik migreren?” Dat werkt beter dan “mijn site is soms stuk”.
Drie concrete scenario’s uit mijn praktijk
Scenario A: Site down direct na migratie naar nieuwe hosting
Symptoom. Migratie afgerond op vrijdagmiddag, DNS gepropageerd, Error establishing a database connection op zowel homepage als wp-admin.
Diagnose. Test-script uit stap 4 gaf Access denied for user 'jouwsite_admin_old'@'localhost'. De DB_USER in wp-config.php verwees nog naar de oude naam bij de oude hoster.
Fix. Nieuwe DB_USER in hostingpaneel gecheckt (was newhost_jouwsite), wp-config.php bijgewerkt met correcte DB_USER, DB_PASSWORD en DB_NAME (die krijgen bij nieuwe hosting bijna altijd een nieuwe prefix). Site was binnen 5 minuten terug.
Preventie. Bij een migratie hoort een pre-migration checklist met alle DB-credentials en post-migration wp-config.php template. Ik werk met een migratie-script dat de vier constanten automatisch vervangt.
Scenario B: Intermitterende error tijdens Black Friday
Symptoom. WooCommerce-shop met 500 tot 800 dagelijkse orders. Op Black Friday: elke 10 tot 15 minuten viel de site 30 tot 60 seconden uit met de database-error. Daartussen: normaal.
Diagnose. Max_used_connections gepiekt op 30 (limiet Combell shared: 30). SHOW PROCESSLIST toonde 20+ threads vast op Copying to tmp table bij dezelfde WooCommerce-report-query.
Fix. Object cache aangezet met Redis Object Cache. WC_Admin background reports uitgezet tijdens de piek, via Woo → Status → Tools → Disable analytics. Autoload cleanup gedaan, waarmee wp_options van 180 MB naar 12 MB ging. En het Combell-pakket vier dagen omhoog naar hun VPS-tier met 100 verbindingen. Uitval stopte na 20 minuten.
Preventie. Voor de Black Friday van 2027 gaat deze klant permanent naar een managed WordPress-hoster.
Scenario C: Site down na stroomstoring datacenter
Symptoom. Zaterdag om 3:00 stroomstoring bij de hostingprovider, systemen 40 minuten uit. Zondag ochtend: site geeft database-error, wp-admin ook onbereikbaar.
Diagnose. Test-script slaagde (Connected: server version 10.11.6-MariaDB), dus credentials en connectie waren prima. Repair via WP_ALLOW_REPAIR toonde: wp_options: Table is marked as crashed and last (automatic?) repair failed.
Fix. WP_ALLOW_REPAIR = true in wp-config.php, repair.php met “Repair and Optimize”. Duurde 4 minuten. Tabel gerepareerd, site terug online. Constante direct verwijderd.
Preventie. Deze klant had geen backup jonger dan 30 dagen. Voor mijn onderhoudsklanten draait UpdraftPlus nightly met retentie 14 dagen naar S3, plus wekelijkse backup naar een tweede bestemming (Google Drive of Wasabi).
Waarom valt je WordPress-database uit?
Beantwoord zes vragen. Je krijgt het waarschijnlijkste onderzoeksspoor en de stappen in een veilige volgorde.
Begin met het patroon. Een blijvende fout vraagt een andere route dan een fout die alleen onder druk verschijnt.
Controleer eerst de verbinding zelf voordat je tabellen repareert of plugins aanpast.
define('WP_ALLOW_REPAIR', true);
wp db repair
mysqlcheck --check --auto-repair DATABASE_NAMEZet WP_ALLOW_REPAIR direct daarna weer uit of verwijder de regel. De WordPress-reparatiepagina werkt zonder login zolang deze constant actief is.Een indicatie op basis van je antwoorden. Maak een back-up voordat je de database repareert. Deel databasewachtwoorden nooit in een supportbericht.
Preventie: dit voorkomt herhalingsproblemen
1. Nightly database backup. UpdraftPlus doet dit gratis (dagelijks, geen tijdstipkeuze) of premium (specifiek tijdstip, meerdere destinations). Hosting-native backups (Antagonist JetBackup, TransIP StackVault, Combell backup, Kinsta automated) draaien onafhankelijk van je site en zijn snel te restoren. Heb minstens één van de twee, en test één keer per kwartaal of restore ook werkt (backups die je nooit test zijn geen backups).
2. Autoload watchdog. Voeg deze query maandelijks aan je onderhoudschecklist toe.
SELECT SUM(LENGTH(option_value)) / 1024 / 1024 AS autoload_mb
FROM wp_options WHERE autoload = 'yes';Boven 5 MB: opruimen. Boven 20 MB: agressief opruimen. Boven 50 MB: dat is waarom je DB piekt bij verkeer.
3. Monitoring met DB-aware check. Better Stack Uptime (voorheen Better Uptime) doet keyword-monitoring: het waarschuwt als een specifieke tekst op je pagina verschijnt of ontbreekt. Configureer dat het alert stuurt zodra "Error establishing a database connection" ergens op de homepage staat. Dan zit je binnen minuten in de fix in plaats van uren later via een klant-mail.
4. Hosting-plan afgestemd op piek, niet gemiddelde. Als je op Black Friday, Sinterklaas of een productlancering vijf keer normaal verkeer verwacht, upgrade een week van tevoren. De €20 extra voor die maand is goedkoper dan één uur downtime.
5. wp-config.php in versiebeheer. Voor sites die ik onderhoud commit ik wp-config.php (zonder gevoelige constanten, die staan in .env of via server-environment) naar een private Git-repo. Bij een crash of onbedoelde edit: git checkout wp-config.php en je bent terug op de laatste werkende versie in 10 seconden.

Wanneer een echte webmaster inschakelen
Los dit zelf op als je stap 1 tot 4 doorloopt. Reken op 30 minuten. Heb je daarna nog geen hypothese, stop dan. Bel in deze gevallen iemand in.
- Test-script slaagt maar site blijft down, en
WP_ALLOW_REPAIRtoont niet-repareerbare tabellen (dan zit je in InnoDB-corruptie territorium). - Je een WooCommerce-shop draait met live orders en de checkout is stuk (omzetimpact per uur weegt de urenprijs meerdere keren op).
- Je geen backup hebt van de laatste 7 dagen en durft niet zomaar
REPAIR TABLEte draaien. - Je aan
wp-config.phpmoet editen maar FTP en SSH werken niet en hosting-support is niet responsief.
Voor mijn klanten kost dit type incident meestal 1 tot 3 uur werk (€70 tot €210). Daarin zit een backup-check, root-cause-documentatie en het opzetten van monitoring. Dan gebeurt het niet nog een keer stiekem.
Twijfel je of een intermitterende fout aan je database ligt of aan iets anders, zoals een plugin-conflict? Kijk dan ook eens naar wanneer een popup of slider ineens niet meer werkt. Daar zit vaak overlap met dezelfde diagnostische reflex.
Vastgelopen op één van deze stappen?
Als je in de diagnose vastloopt of de site heeft omzetimpact, stuur me een bericht via /contact/. Ik kijk binnen kantoortijden binnen 2 uur mee, spoedhulp buiten kantoor in overleg. Ik factureer alleen de daadwerkelijk bestede tijd zonder minimumafname.
Moet deze fout nooit meer voorkomen? Via /diensten/ bied ik een onderhoudscontract met nightly DB-backups, monitoring en preventieve autoload-checks. Dan verrast een corrupte tabel of een verlopen credential je niet meer op een dinsdagochtend.



