Databases
Een .sql-dump lezen zonder importeren: een CLI-audit
Je krijgt op zondagavond een .sql.gz van 4,2 GB van het vorige bureau in je inbox, met één regel erbij: krijg de site maandag weer online. Lees de dump eerst koud vanuit de terminal.

De dump in je inbox om 23 uur
Een klant mailde op zondagavond een .sql.gz van 4,2 GB van het vorige bureau, met één regel erbij: "dit is alles van de oude server, krijg de site alsjeblieft maandag weer online." We hebben hem niet geïmporteerd. Niet zondagavond, niet maandagochtend. We hebben hem eerst gelezen.
Een geërfde dump importeren voordat je weet hoe hij in elkaar zit, is hoe teams uiteindelijk een staging database overhouden die stilletjes twee miljoen rijen session-rommel meedraagt, twee character sets die om dezelfde kolom vechten, of een API-key in plaintext in een wp_options-rij. Twintig minuten met GNU coreutils vertelt je wat je echt geërfd hebt.
De eerste drie commando's
Voordat je iets anders doet, draai deze drie tegen het bestand zoals het op disk staat:
file dump.sql.gz
gunzip -c dump.sql.gz | head -200
gunzip -c dump.sql.gz | wc -lfile bevestigt of het archief echt een gzip-gecomprimeerde mysqldump is, een tarball, of een Windows-encoded UTF-16-bestand dat je terminal opblaast. head -200 toont de mysqldump-header, de serverversie die de dump produceerde, de default character set, en meestal de eerste twee of drie CREATE TABLE-statements. wc -l geeft een line count, de goedkoopste sanity check die er is. Een dump van 4 GB met 12 regels is geschreven met --extended-insert, één INSERT per tabel. Acht miljoen regels betekent per-row inserts, en de import duurt een orde van grootte langer.
Alle tabellen in kaart brengen zonder import
Dit is het werkpaard:
gunzip -c dump.sql.gz | grep -E "^CREATE TABLE" | awk '{print $3}' | sortDertig seconden later heb je de complete tabel-inventaris, gesorteerd, met de prefix zichtbaar. Zie je wp_, wp2_ en old_wp_ in dezelfde dump, gefeliciteerd: je hebt drie half-verwijderde WordPress-installs aan elkaar geplakt geërfd. Zie je jos_, dan is de site Joomla 1.5 van vóór 2012. Zie je zowel jos_ als j25_, dan heeft iemand geprobeerd Joomla te upgraden en is halverwege gestopt.
Voor een snelle schatting van het aantal rijen per tabel, tel de multi-row INSERT-chunks:
gunzip -c dump.sql.gz \
| grep "^INSERT INTO \`wp_posts\`" \
| grep -o "),(" \
| wc -lHet getal is bij benadering (het telt er één te weinig per INSERT-statement en mist single-row-tabellen), maar voor een audit onderscheidt het duizenden rijen van tientallen miljoenen, en dat is het antwoord dat je in dit stadium nodig hebt.
Eén tabel uit een vier-gigabytebestand trekken
Je wilt bijna nooit de hele dump importeren bij de eerste poging. Je wilt één tabel, vaak wp_users of customers, zodat je kunt zien welke kolommen er zijn en hoe de data eruitziet. Het standaard mysqldump-formaat plaatst elke tabel tussen twee voorspelbare comment-markers, en daar is sed precies goed in:
gunzip -c dump.sql.gz \
| sed -n '/^-- Table structure for table `wp_users`/,/^-- Table structure for table/p' \
> wp_users.sqlJe hebt nu een klein bestand met het schema en alle data van één tabel, klaar om in een scratch database te laden. Hetzelfde bereik werkt voor civicrm_contact, oc_products, wat dan ook. Het sluitende patroon (de volgende -- Table structure-marker) maakt het bereik betrouwbaar tussen verschillende mysqldump-versies.
Als het vorige bureau --skip-comments gebruikte, zijn de structure-markers er niet. Val terug op /CREATE TABLE `wp_users`/,/UNLOCK TABLES/p. Trager te typen, maar format-onafhankelijk.
De red flags die je vóór de import wilt vinden
Zodra je de dump kunt lezen, kun je hem auditen. Vier checks die we altijd draaien:
Character set mismatches. Een site die drie keer is gemigreerd, draagt vaak tabellen in utf8, utf8mb4 en latin1 tegelijk:
gunzip -c dump.sql.gz | grep -oE "DEFAULT CHARSET=[a-z0-9_]+" | sort -uKrijg je meer dan één regel terug, reken dan op mojibake. De fix gebeurt bij de import met --default-character-set, maar je kunt niet repareren wat je niet hebt gemeten.
Storage engines. Een verrassend aantal legacy MySQL-dumps levert in 2026 nog steeds MyISAM-tabellen mee. Vind ze:
gunzip -c dump.sql.gz | grep -oE "ENGINE=[A-Za-z]+" | sort | uniq -cMyISAM betekent geen transacties en geen foreign keys, een eigen gesprek op zich. Dat wil je weten vóór je live gaat. De MySQL reference manual heeft het conversiepad.
Plaintext secrets. Zowel WordPress als Drupal cachen API-keys, SMTP-wachtwoorden en signed tokens in options- of variable-tabellen. Grep voordat je importeert, roteer alles wat je vindt:
gunzip -c dump.sql.gz \
| grep -aiE "api[_-]?key|secret|smtp_pass|bearer " \
| head -40De -a-flag vertelt grep om regels die op binary lijken als tekst te behandelen, en dat is van belang als InnoDB iets vreemds in een BLOB-kolom heeft gepropt.
Cache-tabellen zonder grenzen. Vooral Drupal staat erom bekend cache_*-tabellen mee te leveren met miljoenen rijen verlopen session data die niemand ooit heeft getruncated. Ze blazen de dump op, blazen de import op, en hebben nul nut op de nieuwe stack. Een grep "^CREATE TABLE.*cache" van twee seconden brengt ze allemaal naar boven.
Een lange pipe volgen met pv
Zodra de dump over een gigabyte gaat, voelt elk commando hierboven traag. Pipe door pv (Pipe Viewer) en je krijgt een live voortgangsbalk:
pv dump.sql.gz | gunzip | grep -c "^INSERT INTO"Dat is het verschil tussen staren naar een bevroren terminal en weten dat je nog 90 seconden hebt. Installeer met brew install pv op macOS, apt install pv op Debian-achtige Linux. Een uur dat je besteedt aan het koud lezen van een dump wint elke keer van een week debuggen van een half-geïmporteerde.
De audit van vijf minuten
Toen we vorig jaar een Drupal 7 naar WordPress-migratie deden voor een Rotterdams logistiek bedrijf, woog de geërfde dump 6,1 GB gecomprimeerd, maar de helft daarvan was een cache_form-tabel met acht jaar aan ongeflushte session payloads die we met grep en wc vingen voordat er ook maar één import draaide. Zo'n pre-flight check zit in elke legacy migratie die we draaien, want een dump die je écht hebt gelezen is een dump waar je tegen kunt plannen.
Op de volgende geërfde .sql-file die in je inbox belandt: draai file, head -200 en grep -E '^CREATE TABLE' voordat je iets anders doet. Je weet er in 30 seconden meer over dan de meeste teams na een import van vier uur.
Kern
Een uur een dump koud lezen wint van een week debuggen van een half-geïmporteerde. grep, sed en wc vertellen je bijna alles voordat de eerste import draait.
FAQ
Kun je een .sql.gz lezen zonder hem eerst uit te pakken?
Ja. Gebruik zless om te pagineren, of pipe gunzip -c naar less of grep. Geen van beide schrijft een uitgepakte kopie naar disk, en dat is van belang als de dump groter is dan je vrije ruimte.
Wat als de dump UTF-16 is uit een Windows-export?
file markeert dat. Converteer met iconv -f UTF-16LE -t UTF-8 voordat je grept. De meeste CLI-tools gaan uit van single-byte of UTF-8 input en geven anders lege resultaten terug.
Hoe haal ik één rij uit een multi-row INSERT?
Meestal doe je dat niet. Trek de hele tabel eruit met sed, laad hem in een scratch database, en SELECT dan wat je nodig hebt. Multi-row INSERT-syntax met regex parsen is een verloren strijd.
Is mysqldump in 2026 nog steeds het juiste formaat?
Voor audit-werk wel. Het tekstformaat is grep-vriendelijk en versie-portable. Voor backups en grote transfers is de MySQL Shell dump utility sneller en levert hij parallel-loadable output.