Keeping the MySQL or MariaDB server time zone predictable prevents confusing timestamp shifts in application logs, scheduled jobs, replication checks, and user-facing reports when the same data is read across multiple regions.

Both databases track three related values: the OS-derived @@system_time_zone, the server-wide default @@global.time_zone, and each connection's @@session.time_zone. New sessions inherit the global value, functions such as NOW() follow the session setting, and TIMESTAMP columns are converted between the session time zone and UTC while DATETIME values stay as stored.

Examples below use Linux package installs and systemd units because that is where option files and service restarts are easiest to verify. The default global value is usually SYSTEM, so the server follows the host time zone until you set an explicit override; global changes affect only new connections; named zones such as Europe/Berlin require loaded time zone tables; and replicated servers should not mix different host time zones while still relying on SYSTEM. For stable cross-region behavior, keep the database on +00:00 unless the server truly must operate in a local civil time zone.

Steps to set MySQL or MariaDB server time zone:

  1. Open a terminal with a database account that can change global system variables.

    In current MySQL releases, SET GLOBAL time_zone requires SYSTEM_VARIABLES_ADMIN or the deprecated SUPER privilege. Current MariaDB documentation lists SUPER for the same operation.

  2. Check the current global, session, and OS-derived time zone values.
    $ client_bin=$(command -v mariadb || command -v mysql)
    $ "$client_bin" --table --user=root --password --execute "SELECT @@global.time_zone AS global_tz, @@session.time_zone AS session_tz, @@system_time_zone AS system_tz;"
    +-----------+------------+-----------+
    | global_tz | session_tz | system_tz |
    +-----------+------------+-----------+
    | SYSTEM    | SYSTEM     | UTC       |
    +-----------+------------+-----------+

    If the local root account uses Unix socket authentication, replace the explicit credentials with sudo mariadb or sudo mysql.

  3. Set the runtime server default to UTC and align the current session if you want the same shell to reflect the change immediately.
    $ "$client_bin" --table --user=root --password --execute "SET GLOBAL time_zone = '+00:00'; SET SESSION time_zone = '+00:00'; SELECT @@global.time_zone AS global_tz, @@session.time_zone AS session_tz, NOW() AS now_session, UTC_TIMESTAMP() AS now_utc;"
    +-----------+------------+---------------------+---------------------+
    | global_tz | session_tz | now_session         | now_utc             |
    +-----------+------------+---------------------+---------------------+
    | +00:00    | +00:00     | 2026-04-09 21:32:47 | 2026-04-09 21:32:47 |
    +-----------+------------+---------------------+---------------------+

    SET GLOBAL changes the default only for new connections. Existing sessions keep their current session time zone until they reconnect or run SET SESSION time_zone = ... themselves.

    UTC_TIMESTAMP() does not follow the session time zone, so it is a useful comparison when confirming the change.

  4. Open a fresh connection and confirm that new sessions now inherit the server default.
    $ "$client_bin" --table --user=root --password --execute "SELECT @@global.time_zone AS global_tz, @@session.time_zone AS session_tz, @@system_time_zone AS system_tz;"
    +-----------+------------+-----------+
    | global_tz | session_tz | system_tz |
    +-----------+------------+-----------+
    | +00:00    | +00:00     | UTC       |
    +-----------+------------+-----------+
  5. Inspect the server option-file search order before making the change persistent across restarts.
    $ server_bin=$(command -v mariadbd || command -v mysqld)
    $ sudo "$server_bin" --verbose --help 2>/dev/null | sed -n '/Default options are read from the following files in the given order:/,+3p'
    Default options are read from the following files in the given order:
     /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
    ##### snipped #####

    Use the last server include directory that the base file actually reads, such as /etc/mysql/mariadb.conf.d/, /etc/mysql/mysql.conf.d/, or /etc/mysql/conf.d/. This guide covers that discovery in more detail.

  6. Create or edit a dedicated server override file under the active server option group.
    $ sudoedit /etc/mysql/conf.d/time-zone.cnf

    [mysqld] is the safest cross-compatible option group. MariaDB also reads [mariadb] and [mariadbd].

    In option files, MySQL and MariaDB treat dashes and underscores in option names as equivalent, so default-time-zone and default_time_zone are interchangeable spellings.

  7. Add the startup default time zone to the server option file.
    [mysqld]
    default-time-zone = '+00:00'

    A typo or a bad option group can stop the database server from starting. Keep the change in a small dedicated override file so it is easy to remove if startup fails.

  8. Identify and restart the active database service unit so the on-disk change becomes the new global default.
    $ systemctl list-unit-files --type=service | grep --extended-regexp '^(mysql|mariadb|mysqld)\\.service'
    mariadb.service                              enabled         enabled
    $ sudo systemctl restart mariadb
    $ systemctl is-active mariadb
    active

    Replace mariadb with the discovered unit name, which may be mysql or mysqld on other packages.

  9. Confirm the persisted setting from a new client connection after the restart.
    $ "$client_bin" --table --user=root --password --execute "SELECT @@global.time_zone AS global_tz, @@session.time_zone AS session_tz, @@system_time_zone AS system_tz;"
    +-----------+------------+-----------+
    | global_tz | session_tz | system_tz |
    +-----------+------------+-----------+
    | +00:00    | +00:00     | UTC       |
    +-----------+------------+-----------+

Use a named time zone

  1. Check whether the time zone tables are loaded before setting an IANA zone name.
    $ "$client_bin" --table --user=root --password --execute "SELECT COUNT(*) AS zone_rows FROM mysql.time_zone_name;"
    +-----------+
    | zone_rows |
    +-----------+
    |         0 |
    +-----------+

    Both products create the tables by default, but leave them unpopulated until you load zoneinfo data.

  2. Load the system zoneinfo database into the MySQL or MariaDB time zone tables.
    $ tz_loader=$(command -v mariadb-tzinfo-to-sql || command -v mysql_tzinfo_to_sql)
    $ "$tz_loader" /usr/share/zoneinfo | "$client_bin" --user=root --password mysql

    MySQL documentation recommends restarting the server after loading or reloading the time zone tables so cached time zone data is refreshed. A restart is also the safest cross-engine choice before retrying a named zone.

  3. Restart the same database service unit you identified earlier, then set the named zone.
    $ sudo systemctl restart mariadb
    $ "$client_bin" --table --user=root --password --execute "SET GLOBAL time_zone = 'Europe/Berlin'; SELECT @@global.time_zone AS global_tz;"
    +---------------+
    | global_tz     |
    +---------------+
    | Europe/Berlin |
    +---------------+

    Use a named zone only when the server must follow local daylight-saving rules automatically. Otherwise, staying on +00:00 is usually simpler and safer.

Troubleshooting

  1. If ERROR 1298 (HY000): Unknown or incorrect time zone appears, the named zone tables are not loaded yet, the server has not been restarted after a reload, or the zone name is misspelled.
  2. If new connections still show SYSTEM after a restart, the setting is in the wrong option file, under the wrong option group, or overridden later in the include chain. Recheck the effective options with my_print_defaults mysqld on MySQL or my_print_defaults mariadbd on MariaDB.
  3. If existing applications continue showing the old local time after SET GLOBAL time_zone, reconnect them or set the session value explicitly because running sessions keep their current @@session.time_zone.