Mojibake after a MySQL move can come from incorrect stored bytes, misleading column metadata, the dump or restore connection, or the new application connection. Do not run a blanket conversion until you know which layer changed.
Last updated: September 26, 2026.
SELECT id,
display_name,
HEX(display_name) AS stored_bytes
FROM customers
WHERE id IN (101, 205, 319);
SELECT @@character_set_client,
@@character_set_connection,
@@character_set_results;Compare the hexadecimal bytes and visible values on the old and new systems. This separates data corruption from a display or connection problem.
Classify the failure
- Correct bytes, wrong display: fix the connection or response encoding.
- Wrong bytes in new server only: inspect dump and restore settings.
- Wrong bytes on both servers: metadata may never have matched the original encoding.
- Some rows correct and some broken: repair only a proven subset.
Also inspect database, table, and column character sets in information_schema.columns. The database default does not override an existing column definition.
Repair a copy, not production first
Restore a backup into a staging database and test one representative column. When text was stored as UTF-8 bytes in a latin1-declared column, a binary intermediate can preserve bytes while correcting metadata; when bytes were actually converted twice, the repair is different. Export before-and-after hex values and confirm them with native speakers or authoritative source data.
After the data is correct, follow the staged utf8mb4 conversion procedure rather than changing defaults alone.
Prevent another mismatch
Configure the driver to use utf8mb4, keep schema definitions consistent, and emit matching HTTP and HTML declarations. The existing meta charset versus HTTP header guide explains the browser side. Add round-trip tests containing accents, non-Latin scripts, emoji, and smart punctuation before the final cutover.