Chapter 02 · Server Architecture, Processes, Files, Connections, and Configuration
Character Sets, Collations, Time Zones, Locales, and Server Defaults
Understand MySQL character sets, collations, connection encoding, time zones, locale settings, and inherited defaults through multilingual text and temporal behavior experiments.
Learning outcomes
ServiceHub accepts technician names, customer notes, and appointment timestamps from clients in several countries. A developer sees that the table is declared utf8mb4 and assumes text is safe. Another developer stores local appointment time in a TIMESTAMP column without checking the session time zone. Both can produce data that looks correct in one session and wrong in another.
MySQL has layered defaults for character sets, collations, and time-related behavior. The server, database, table, column, and connection can each participate. This lesson makes those layers observable and shows how to choose explicit boundaries so data interpretation does not depend on accidental client defaults.
Explain character set versus collation, and identify server/database/table/column/connection defaults.
Use utf8mb4 deliberately and avoid the deprecated utf8 alias that refers to utf8mb3 in MySQL 8.4.
Observe how connection character-set variables affect incoming statements and result interpretation.
Compare case/accent-sensitive and insensitive collations with exact query evidence rather than assumptions.
Explain session time_zone behavior and the practical difference between TIMESTAMP and DATETIME for cross-time-zone applications.
A character set answers “which characters and encodings are representable?” A collation answers “how should strings in that character set compare and sort?” Time-zone settings are a separate interpretation layer for temporal values.
Character-set defaults are inherited, not magically universal
MySQL can specify character sets at multiple levels. If you omit an explicit lower-level setting, MySQL normally inherits from the enclosing default. This is convenient, but it means a table created in one schema can behave differently from an identical-looking CREATE TABLE run in another schema if their defaults differ.
SELECT @@character_set_server AS server_charset, @@collation_server AS server_collation, @@character_set_database AS database_charset, @@collation_database AS database_collation;SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAMEFROM information_schema.SCHEMATAWHERE SCHEMA_NAME = 'servicehub';In MySQL 8.4 the default server character set is utf8mb4 and the default collation is utf8mb4_0900_ai_ci, but explicit inspection is still preferable to relying on a documented default: packages, startup options, migrations, or older schemas can differ.
The utf8 name is a deprecated synonym for utf8mb3 in MySQL 8.4. For new Unicode data, use utf8mb4 explicitly. It supports the full Unicode range, including supplementary characters such as many emoji.
Database, table, and column inheritance
Create a disposable schema and table that make the inheritance chain visible. Do not use this lab to migrate production text data.
CREATE DATABASE IF NOT EXISTS servicehub_i18n CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;USE servicehub_i18n;CREATE TABLE customer_name_demo ( id BIGINT PRIMARY KEY AUTO_INCREMENT, display_name VARCHAR(200) NOT NULL, exact_code VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs NOT NULL) ENGINE=InnoDB;SHOW CREATE TABLE customer_name_demo;SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COLLATIONFROM information_schema.TABLESWHERE TABLE_SCHEMA='servicehub_i18n' AND TABLE_NAME='customer_name_demo';SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAMEFROM information_schema.COLUMNSWHERE TABLE_SCHEMA='servicehub_i18n' AND TABLE_NAME='customer_name_demo';The first column inherits the table/database collation. The exact_code column overrides it with an accent-sensitive, case-sensitive collation. Use explicit column collations only where the business rule requires them; a schema full of arbitrary mixed collations becomes harder to reason about and can cause conversion costs or errors in comparisons.
Connection character sets: storage is only half the path
A client sends statement text as bytes. The server needs to know how to interpret those bytes, and the client needs to interpret result bytes correctly. MySQL tracks this through session variables including character_set_client, character_set_connection, and character_set_results, with associated collation state.
SELECT @@character_set_client, @@character_set_connection, @@character_set_results, @@collation_connection;SET NAMES utf8mb4 COLLATE utf8mb4_0900_ai_ci;SELECT @@character_set_client, @@character_set_connection, @@character_set_results, @@collation_connection;SET NAMES is a useful SQL demonstration, but production applications should normally configure the connector/driver to use the intended character set at connection creation. That keeps the driver and server in agreement and avoids a window in which statements run under an unintended connection encoding.
A table declared utf8mb4 cannot repair bytes that the client and server already interpreted inconsistently. Encoding correctness is end-to-end: source text, driver configuration, connection variables, column character set, and output consumer all matter.
Collation is a business rule about comparison
The suffixes in modern utf8mb4 collations encode important behavior. For example, ai means accent-insensitive, as accent-sensitive, ci case-insensitive, and cs case-sensitive. Do not infer every linguistic detail from the suffix alone; use the documented collation and test your real data.
SELECT 'Cafe' COLLATE utf8mb4_0900_ai_ci = 'café' COLLATE utf8mb4_0900_ai_ci AS ai_ci_equal;SELECT 'Cafe' COLLATE utf8mb4_0900_as_cs = 'café' COLLATE utf8mb4_0900_as_cs AS as_cs_equal;SELECT 'ABC' COLLATE utf8mb4_0900_ai_ci = 'abc' COLLATE utf8mb4_0900_ai_ci AS case_insensitive_equal;SELECT 'ABC' COLLATE utf8mb4_0900_as_cs = 'abc' COLLATE utf8mb4_0900_as_cs AS case_sensitive_equal;Expected pattern: the accent/case-insensitive comparisons can return equality where the accent/case-sensitive comparisons do not. The exact collation semantics are part of your data model: usernames, identifiers, human names, search fields, and legal codes can need different rules.
Changing a collation later can change uniqueness behavior and index ordering. Treat collation migrations as schema changes that require duplicate detection and query testing, not cosmetic metadata edits.
Failure lab: the client says UTF-8, but the server hears something else
A common bad approach is to create utf8mb4 columns and assume every client automatically speaks utf8mb4. Reproduce the diagnostic path without deliberately corrupting important data.
- Query the four connection character-set/collation variables before inserting anything.
- Use a disposable table containing characters outside plain ASCII, for example
José,تهران,東京, or an emoji. - Insert through the client configured correctly for utf8mb4 and verify with
HEX(),CHAR_LENGTH(), andLENGTH(). - If you want to demonstrate a mismatch, do it only in a disposable session/table and restore the connection setting immediately. Different clients may reject incompatible settings differently, so document the observed result instead of promising one universal error.
INSERT INTO customer_name_demo(display_name, exact_code)VALUES ('José 🚚', 'TECH-A1');SELECT display_name, CHAR_LENGTH(display_name) AS characters, LENGTH(display_name) AS bytes, HEX(display_name) AS encoded_bytesFROM customer_name_demoWHERE exact_code='TECH-A1';For multibyte character sets, LENGTH() reports bytes while CHAR_LENGTH() reports characters. A four-byte utf8mb4 character can make byte length larger than character count.
Session time zones and two temporal storage models
MySQL's time_zone variable can be global and session-scoped. A session can use SYSTEM, a numeric UTC offset such as +00:00 or +03:30, or a named zone when the server's time-zone tables are populated. Numeric offsets work without loading named-zone tables and are therefore useful for a reproducible lab.
TIMESTAMP and DATETIME solve different problems. MySQL converts TIMESTAMP values between the session time zone and UTC for storage/retrieval. DATETIME stores the calendar fields you provide without the same automatic time-zone conversion. This distinction can be useful—but only if your application contract is explicit.
DROP TABLE IF EXISTS servicehub_i18n.time_demo;CREATE TABLE servicehub_i18n.time_demo ( id INT PRIMARY KEY, event_ts TIMESTAMP NOT NULL, event_dt DATETIME NOT NULL);SET SESSION time_zone = '+00:00';INSERT INTO servicehub_i18n.time_demoVALUES (1, '2026-08-16 10:00:00', '2026-08-16 10:00:00');SELECT @@SESSION.time_zone, event_ts, event_dtFROM servicehub_i18n.time_demo;SET SESSION time_zone = '+03:30';SELECT @@SESSION.time_zone, event_ts, event_dtFROM servicehub_i18n.time_demo;Expected pattern: after switching the session to +03:30, the TIMESTAMP representation shifts by 3 hours 30 minutes, while the DATETIME fields remain 10:00:00. This is observable behavior, not a recommendation that one type is always better.
For an absolute event instant such as “job created at,” a UTC-oriented timestamp contract is often appropriate. For a wall-clock concept such as “shop opens at 09:00 local time,” you may need a local datetime plus explicit zone/locale context. Chapter 03 covers temporal types more deeply.
Locale is not the same as character set or time zone
Locale-sensitive presentation variables such as lc_time_names affect names produced by certain date-formatting operations. They do not change stored timestamp instants, client encoding, or collation. Keeping these dimensions separate prevents a configuration change intended for presentation from being mistaken for a storage migration.
SELECT @@SESSION.time_zone, @@SESSION.lc_time_names, @@SESSION.character_set_connection, @@SESSION.collation_connection;SELECT DATE_FORMAT('2026-08-16', '%W, %M %e, %Y') AS localized_label;In application architectures, formatting is often performed outside the database using the user's locale. If you use MySQL locale-sensitive functions, document that dependency and test it like any other output contract.
Hands-on lab: define the ServiceHub text/time contract
- Record the server, database, connection, table, and column character-set/collation values for the ServiceHub lab.
- Create the disposable
customer_name_demotable and prove the comparison difference betweenai_ciandas_cs. - Insert multilingual text through your actual client and verify it with
HEX(),CHAR_LENGTH(), and a round-trip read. - Create
time_demo, insert under+00:00, read under+03:30, and explain the TIMESTAMP versus DATETIME result in your own words. - Reset the session time zone to its original value and drop only the disposable demo tables/schema if you created them solely for this lesson.
Knowledge check
- Why does a utf8mb4 table definition not by itself guarantee correct client text handling?
- What business behavior does a collation control?
- Why should new MySQL 8.4 schemas prefer utf8mb4 over the utf8 alias?
- What happens to a TIMESTAMP display when the session time zone changes?
- Why is DATETIME not automatically “better” just because it does not shift with time_zone?
Reveal answers
- The client/server connection also has character-set interpretation; bytes can be misinterpreted before storage.
- String comparison and ordering rules, including case/accent sensitivity and linguistic ordering.
utf8is a deprecated alias forutf8mb3;utf8mb4supports the full Unicode range.- MySQL converts the stored instant for presentation in the new session zone.
- DATETIME stores calendar fields without that conversion, which may be wrong for absolute instants; the correct type depends on the application's temporal contract.
Production judgment and references
Choose one documented application character-set policy, normally utf8mb4 for modern Unicode applications, and enforce it in schema migrations and connector configuration. Choose collations from actual comparison requirements. Test uniqueness, ordering, search, and multilingual data before changing a production collation.
For time, decide explicitly whether each value represents an absolute instant, a local civil time, a recurring schedule, or a date-only concept. Store the additional zone/offset information your domain needs. Monitor connection initialization so pools do not silently inherit different time_zone, sql_mode, or character-set settings after deployments.
Authoritative references
- MySQL 8.4 Reference Manual — Character Sets, Collations, Unicode
- MySQL 8.4 Reference Manual — Connection Character Sets and Collations
- MySQL 8.4 Reference Manual — Configuring Application Character Set and Collation
- MySQL 8.4 Reference Manual — utf8mb4 Character Set
- MySQL 8.4 Reference Manual — MySQL Server Time Zone Support
Next: bring the chapter together by validating configuration before restart, reading startup failures from authoritative evidence, and recording a baseline server profile for every later lab.