MySQL Time Zone 변경 방법

    개요

    글로벌 서비스를 하면서 Time Zone 설정은 신경써야 할 부분이 된다. 본 포스트에서는 MySQL의 Time Zone을 설정하는 방법에 대해 정리한다. 테스트의 편의상 Docker를 기반으로 테스트하였다.

     

    현재 설정 확인

    mysql> select @@global.time_zone,  @session.time_zone;
    +--------------------+----------------------------------------+
    | @@global.time_zone | @session.time_zone                     |
    +--------------------+----------------------------------------+
    | SYSTEM             | 0x                                     |
    +--------------------+----------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | SYSTEM              |
    +--------------------+---------------------+
    1 row in set (0.00 sec)
    
    mysql> show variables like '%time_zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.12 sec)

    위와 같이, time_zone 변수로 현재 설정을 확인할 수 있다.

     

    설정 방법

    Time Zone 설정은, OS 수준에서의 설정, MySQL 자체 설정 변경, 그리고 접속하는 클라이언트 수준에서의 변경 등으로 방법이 다양하다. Time Zone을 명시할 때는, +09:00 와 같은 offset 방식과, Asia/Seoul 과 같은 named zone 방식의 표기가 모두 가능하다. (단, 개인 설치 환경에 따라 추가 설정이 필요할 수도 있다.)

     

    시스템 변수 설정

    MySQL이 동작하는 OS 수준에서의 설정 방법이다. MySQL도 자신이 동작하는 OS의 설정을 따르게 된다. 따라서, 환경 변수를 설정하면 Time Zone을 변경할 수 있다. 본 포스트에서는 테스트의 편의상 Docker를 사용하므로, Docker Container에서 해당 환경 변수를 변경하고자 한다.

     

    Docker 기반 MySQL 설치하기

    Docker를 사용하여 MySQL을 설치하는 방법을 정리한다. docker-compose.yml YAML 파일의 기본 골격을 다음과 같이 작성한다. version: "3" services: db: image: mysql:8.0.20 container_name: mysql_db restart:..

    luran.me

     

    윗글 작성시 사용한 설정을 다음과 같이 변경하였다.

    version: "3"
    services:
        db:
            image: mysql:8.0.20
            container_name: mysql_db
            restart: always
            ports:
                - "3306:3306"
            environment:
                MYSQL_DATABASE: "${MYSQL_DATABASE}"
                MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
                MYSQL_USER: "${DB_USER_ID}"
                MYSQL_PASSWORD: "${DB_USER_PASSWORD}"
                TZ: US/Hawaii
            command:
                - --character-set-server=utf8mb4
                - --collation-server=utf8mb4_unicode_ci
            volumes:
                - ${MYSQL_HOME_DIR}/volumes/mysql/:/var/lib/mysql/
                - ${MYSQL_HOME_DIR}/conf/:/etc/mysql/conf.d/

    environment (환경변수) 선언부에, TZ를 추가로 기록하였다. 서버를 다시 띄워서 time_zone 관련 정보를 확인해 보면 다음과 같다.

    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | SYSTEM              |
    +--------------------+---------------------+
    1 row in set (0.01 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | HST    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.19 sec)
    
    mysql> select now();
    +---------------------+
    | now()               |
    +---------------------+
    | 2021-05-08 00:05:14 |
    +---------------------+
    1 row in set (0.00 sec)

    US/Hawaii로 설정했고, system_time_zone은 HST로 변경된 것을 확인할 수 있다.

     

    서버 설정

    이제, 위에서 설정한 TZ 설정은 원복하고, MySQL의 config 파일에 Time Zone 설정을 지정해 보자.

    [mysqld]
    default-time-zone='+9:00'

    mysql.cnf 파일에 위와 같이 설정을 변경하였고, 서버를 다시 띄운 후 접속하여 확인한 결과는 아래와 같다. 설정을 기록할 때, 오타 조심하자. mysqld로 적어야 한다. mysql로 적으면 적용되지 않고 Unknown Variable 에러가 발생한다. (경험담)

    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | +09:00             | +09:00              |
    +--------------------+---------------------+
    1 row in set (0.00 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | +09:00 |
    +------------------+--------+
    2 rows in set (0.10 sec)
    
    mysql> select now();
    +---------------------+
    | now()               |
    +---------------------+
    | 2021-05-08 19:56:43 |
    +---------------------+
    1 row in set (0.00 sec)

    위와 같이 mysqld 설정을 사용하지 않고, 명령어로 지정하면 어떨까?

    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | SYSTEM              |
    +--------------------+---------------------+
    1 row in set (0.00 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.11 sec)
    
    mysql> set @@global.time_zone = '+08:00';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | +08:00 |
    +------------------+--------+
    2 rows in set (0.02 sec)
    
    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | +08:00             | SYSTEM              |
    +--------------------+---------------------+
    1 row in set (0.00 sec)

    위와 같이 설정하면, MySQL 자체를 재시작하지 않더라도 동적 설정은 가능하다. 그러나, 영구적 저장은 되지 않으므로 설정을 보존하고 싶으면 mysqld 영역에 설정을 지정해야 할 것이다. 아래와 같이 한 세션에서 설정하고, 다른 세션을 추가로 맺어서 동일하게 timezone이 유지되는지 확인할 수 있다.

    // 세션-1
    mysql> set global time_zone = 'Asia/Tokyo';
    Query OK, 0 rows affected (0.09 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+------------+
    | Variable_name    | Value      |
    +------------------+------------+
    | system_time_zone | UTC        |
    | time_zone        | Asia/Tokyo |
    +------------------+------------+
    2 rows in set (0.07 sec)
    
    // 세션-2
    mysql> show global variables like '%zone%';
    +------------------+------------+
    | Variable_name    | Value      |
    +------------------+------------+
    | system_time_zone | UTC        |
    | time_zone        | Asia/Tokyo |
    +------------------+------------+
    2 rows in set (0.04 sec)

     

    세션 설정

    접속하는 사용자의 세션별로 Time Zone을 개별 설정하게 하는 방법도 알아보자.

    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | SYSTEM              |
    +--------------------+---------------------+
    1 row in set (0.01 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.15 sec)
    
    mysql> set @@session.time_zone = 'Asia/Seoul';
    Query OK, 0 rows affected (0.07 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.10 sec)
    
    mysql> show global variables like '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | UTC    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.02 sec)
    
    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | Asia/Seoul          |
    +--------------------+---------------------+
    1 row in set (0.01 sec)
    
    mysql> show session variables like '%zone%';
    +------------------+------------+
    | Variable_name    | Value      |
    +------------------+------------+
    | system_time_zone | UTC        |
    | time_zone        | Asia/Seoul |
    +------------------+------------+
    2 rows in set (0.12 sec)

    위에서 보다시피, set time_zone 혹은 set @@session.time_zone의 명령어로 세션의 Time Zone 설정을 변경하면, 세션 기준으로 설정을 변경할 수 있다. 위와 같이 설정한 세션 #1과 신규로 접속하는 세션 #2는 설정이 공유되지 않는다. (세션 #1에서 설정했다 하더라도, 세션 #2에 영향을 주지 않음)

    // 새로 접속한 세션에서의 Time Zone 정보 (위의 설정이 반영되지 않는다.
    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | SYSTEM              |
    +--------------------+---------------------+
    1 row in set (0.00 sec)

    이를 자동화 하기 위해, 다음과 같이 추가 설정을 할 수도 있다.

    [mysql]
    init_command="SET time_zone='+09:00'"

    또는,

    [client]
    init_command="SET time_zone='+08:00'"

    와 같이 mysql 섹션 혹은 client 섹션을 선언하고 init command를 지정하면, 클라이언트로 세션을 맺을 때 Time Zone이 설정될 것이다.

    // 신규 접속한 세션
    // 별도 Time Zone을 설정하지 않았고, 위의 설정이 반영되었음
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> select @@global.time_zone, @@session.time_zone;
    +--------------------+---------------------+
    | @@global.time_zone | @@session.time_zone |
    +--------------------+---------------------+
    | SYSTEM             | +08:00              |
    +--------------------+---------------------+
    1 row in set (0.01 sec)

     

    참고

     

    MySQL :: Time zone description tables

    Please don't use this package if your system includes zoneinfo files (e.g. Linux, FreeBSD, Sun Solaris) Please generate the mysql.time_zone* tables from those files using the mysql_tzinfo_to_sql utility instead! (Otherwise you may cause a difference in dat

    dev.mysql.com

     

    댓글

    Designed by JB FACTORY