MY.L6.CHARACTER_SET_SERVER_NOT_UTF8MB4 — a default charset that quietly cannot hold your data
- Category: safety
- Level: 6
- Confidence: deterministic
- Downtime class: none
- Stability: stable
- Suites: audit
- Applies to: MySQL 8.4
- Not transferable to MariaDB: this page describes MySQL 8.4 behavior. MariaDB answers the same driver and does not share these semantics, so SQLens refuses it outright rather than reasoning about it — see drivers/unsupported.
A database or table created without an explicit CHARACTER SET takes the server's.
Laravel's schema builder does emit one for the tables it creates, from
config('database.connections.mysql.charset'). So the common failure is not those tables — it is
everything else:
- a database an operator created by hand,
- a table added by hand,
- a temporary table,
- a migration written in raw SQL.
On latin1 those objects cannot hold most of Unicode. Depending on the SQL mode, MySQL replaces
the character or truncates the value at it rather than refusing the write. The row is stored,
altered, and nobody finds out until somebody asks why their name is wrong.
utf8mb3 is the trap that looks solved
It is called out by name rather than lumped in with latin1. It is three bytes per character and
covers only the Basic Multilingual Plane — so it holds most of what anyone tests with, and silently
cannot store an emoji.
The name is the trap: it says utf8 and it is not.
Flagged
SET GLOBAL character_set_server = latin1;
Preferred
SET GLOBAL character_set_server = utf8mb4;
Why this is one rule and not two
collation_server is not a separate finding, because MySQL will not let the two disagree.
Measured on 8.4.10:
| Statement | Effect on the other variable |
|---|---|
SET character_set_server = latin1 | collation_server became latin1_swedish_ci |
SET collation_server = utf8mb4_unicode_ci | character_set_server became utf8mb4 |
They are one setting with two names. A second rule would report the same misconfiguration twice under two ids — and an ignore-list entry for one would leave the other one shouting.
What is deliberately not judged
Which utf8mb4 collation the server carries. utf8mb4_0900_ai_ci and utf8mb4_unicode_ci are
both legitimate, and the second pins an older Unicode version — a real reason on a database that has
to keep sort order stable across a MySQL upgrade.
The charset is a correctness question. The collation within it is a decision.
Sources
- Server character set and collation — MySQL 8.4
- The utf8mb4 character set — MySQL 8.4
- Connection character sets and collations — MySQL 8.4