Default character set divergence between Windows and Linux table creation in MariaDB
0 reputation · 17 Aug 2024, 04:27 UTC
0 reputation · 17 Aug 2024, 04:27 UTC
MariaDB's default character set for newly created tables varies by operating system: latin1 on Windows and utf8mb3 on Linux, as documented since early releases. This platform-dependent fallback can produce inconsistent schema outputs when the same initialization scripts are deployed across mixed environments. A team migrating a workload from a Linux-based container to a Windows server may observe that newly provisioned tables adopt latin1 as the default, potentially causing silent data truncation for multilingual content unless explicitly overridden per table. The server configuration parameters character_set_server and collation_server can be set at startup, but their interaction with the OS-driven default during table creation remains ambiguous in the documentation, particularly for dynamic provisioning without a restart. Given an application schema relying on utf8mb4, it is unclear whether setting character_set_server=utf8mb4 at startup propagates to new tables without explicit CHARSET clauses, or whether the OS fallback takes precedence. It is also uncertain if the behavior differs between InnoDB and Aria storage engines during a single session.
Yes — if character_set_server is explicitly set when the server starts, it wins on every platform. The OS-specific fallback (latin1 on Windows, utf8mb3 on many Linux builds) only applies when neither character_set_server nor character_set_database has been configured. Setting character_set_server=utf8mb4 (and a matching collation_server) in the option file and restarting gives you a uniform default for all subsequently created tables, on both InnoDB and Aria, with no per-table CHARSET clause required.
Confirmed: The platform divergence exists because the fallback path reads an OS-dependent default at server initialization. This has been the behavior since at least the MariaDB 10.0 era. It is a startup-time decision, not a per-session or per-engine one.
Likely explanation for your migration symptom: The Windows installation almost certainly ships a default my.ini that either sets character_set_server=latin1 explicitly or leaves it unset, so the latin1 fallback engages. Your Linux containers presumably had it set (or relied on the utf8mb3 fallback). The fix is configuration, not schema changes.
The reliable method is the option file, because the fallback is resolved once at startup:
[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ciThen restart and verify:
SHOW VARIABLES LIKE 'character_set_server';
CREATE TABLE charset_probe (id INT);
SHOW CREATE TABLE charset_probe\G
DROP TABLE charset_probe;The SHOW CREATE TABLE output should end with DEFAULT CHARSET=utf8mb4.
Runtime caveat: SET GLOBAL character_set_server=utf8mb4; does affect new tables in current versions, but it is not durable — it vanishes on restart, and it never retroactively changes existing tables or databases. Worse, a database created earlier carries its own default charset, which overrides the server default for new tables in that schema. So treat the option file as the enforcement point and runtime SET only as a stopgap. Also note that init_connect/SET NAMES only changes connection charsets (character_set_client etc.), not table defaults — it will not solve this problem.
There is no engine-specific divergence in default charset selection. Both engines inherit the table default from the effective server (or database) charset at CREATE TABLE time. Verify on your build with:
CREATE TABLE t_innodb (id INT) ENGINE=InnoDB;
CREATE TABLE t_aria (id INT) ENGINE=Aria;
SHOW CREATE TABLE t_innodb\G
SHOW CREATE TABLE t_aria\GThe DEFAULT CHARSET values should be identical.
If tables still come out latin1 after setting the option file, check whether the affected schemas were created earlier: SELECT schema_name, default_character_set_name FROM information_schema.schemata;. A database-level latin1 default will silently override your server setting for new tables, and fixing it requires ALTER DATABASE ... CHARACTER SET utf8mb4 — that, not the server variable, is the most common reason the override 'doesn't work' in practice.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.