Changes between Initial Version and Version 1 of MariaDB TIMESTAMP


Ignore:
Timestamp:
Nov 11, 2025, 10:36:13 AM (4 weeks ago)
Author:
yongwoo
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • MariaDB TIMESTAMP

    v1 v1  
     1[[PageOutline]]
     2= MariaDB TIMESTAMP =
     3
     4== TIMESTAMP와 DATETIME 비교 ==
     5=== 1. time_zone ===
     6DATETIME은 항상 입력한 값 그대로 일정하지만  TIMESTAMP는 time_zone 변수에 따라 값을 자동 변환하여 처리한다.
     7{{{
     8MariaDB> CREATE OR REPLACE TABLE timezone_test ( dt DATETIME, ts TIMESTAMP );
     9
     10MariaDB> SET time_zone = 'Asia/Seoul';
     11MariaDB> INSERT INTO timezone_test VALUES ((NOW()),(NOW()));
     12MariaDB> SELECT * FROM timezone_test;
     13+---------------------+---------------------+
     14| dt                  | ts                  |
     15+---------------------+---------------------+
     16| 2022-11-01 12:40:23 | 2022-11-01 12:40:23 |
     17+---------------------+---------------------+
     18
     19MariaDB> SET time_zone = 'America/New_York';
     20MariaDB> SELECT * FROM timezone_test;
     21+---------------------+---------------------+
     22| dt                  | ts                  |
     23+---------------------+---------------------+
     24| 2022-11-01 12:40:23 | 2022-10-31 23:40:23 |
     25+---------------------+---------------------+
     26}}}
     27
     28따라서 글로벌 환경을 감안해서 개발할 때는 DATETIME보다 TIMESTAMP를 사용해야 한다. 그러나, 글로벌 환경이 아닌 경우에는 굳이 복잡하게 TIMESTAMP를 사용하는 것보다는 DATETIME을 사용하는 것이 간단하다.
     29
     30'''주의''' 글로벌 환경이 아니더라도 일광절약 시간제를 사용한다면 TIMESTAMP를 고려한다.
     31
     32=== 2. 디폴트 값 ===
     33TIMESTAMP는 time_zone 변수에 따라 값을 자동 변환하여 처리하는 특성 외에 다른 여러 특징이 있다.
     34
     35TIMESTAMP는 레코드를 삽입하거나 업데이트할 때 명시적으로 값을 지정하지 않거나 Null을 지정하면 디폴트로 현재 시각을 자동으로 저장한다. 따라서, '''데이터를 입력하거나 수정한 시간을 저장'''하기 편하다.
     36
     37자동으로 저장하는 속성은 레코드의 첫 번째 TIMESTAMP 컬럼에만 적용된다. 두번째 TIMESTAMP 컬럼부터는 변경되지 않는다.
     38{{{
     39MariaDB> CREATE OR REPLACE TABLE timestamp_test (id INT, ts1 TIMESTAMP, ts2 TIMESTAMP);
     40MariaDB> INSERT INTO timestamp_test (id) VALUES (1);
     41MariaDB> SELECT * FROM timestamp_test;
     42+------+---------------------+---------------------+
     43| id   | ts1                 | ts2                 |
     44+------+---------------------+---------------------+
     45|    1 | 2022-11-01 00:01:45 | 0000-00-00 00:00:00 |
     46+------+---------------------+---------------------+
     47
     48MariaDB> UPDATE timestamp_test SET id = 2 WHERE id = 1;
     49MariaDB> SELECT * FROM timestamp_test;
     50+------+---------------------+---------------------+
     51| id   | ts1                 | ts2                 |
     52+------+---------------------+---------------------+
     53|    2 | 2022-11-01 00:02:38 | 0000-00-00 00:00:00 |
     54+------+---------------------+---------------------+
     55}}}
     56
     57==== 2.1. TIMESTAMP의 디폴트 값을 없애려면 ====
     58현재 시각이 자동 저장되는 특성을 없애려면 DEFAULT 값을 Null이 아닌 다른 값으로 지정하면 된다.
     59{{{
     60MariaDB> CREATE OR REPLACE TABLE timestamp_test1 (id INT, ts TIMESTAMP DEFAULT 0);
     61MariaDB> INSERT INTO timestamp_test1 (id) VALUES (1);
     62MariaDB> SELECT * FROM timestamp_test1;
     63+------+---------------------+
     64| id   | ts                  |
     65+------+---------------------+
     66|    1 | 0000-00-00 00:00:00 |
     67+------+---------------------+
     68
     69MariaDB> UPDATE timestamp_test1 SET id = 2 WHERE id = 1;
     70MariaDB> SELECT * FROM timestamp_test1;
     71+------+---------------------+
     72| id   | ts1                 |
     73+------+---------------------+
     74|    2 | 0000-00-00 00:00:00 |
     75+------+---------------------+
     76}}}
     77
     78==== 2.2. DATETIME에도 디폴트 값을 지정하려면 ====
     79DATETIME 컬럼에도 TIMESTAMP처럼 레코드를 삽입하거나 업데이트할 때 디폴트로 현재 시각을 자동으로 저장하려면 DEFAULT CURRENT_TIMESTAMP 와 ON UPDATE CURRENT_TIMESTAMP를 지정해주면 된다.
     80{{{
     81MariaDB> CREATE OR REPLACE TABLE datetime_test ( id INT, dt1 DATETIME DEFAULT CURRENT_TIMESTAMP, dt2 DATETIME ON UPDATE CURRENT_TIMESTAMP, dt3 DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
     82MariaDB> DESC datetime_test;
     83+-------+----------+------+-----+---------------------+-------------------------------+
     84| Field | Type     | Null | Key | Default             | Extra                         |
     85+-------+----------+------+-----+---------------------+-------------------------------+
     86| id    | int(11)  | YES  |     | NULL                |                               |
     87| dt1   | datetime | YES  |     | current_timestamp() |                               |
     88| dt2   | datetime | YES  |     | NULL                | on update current_timestamp() |
     89| dt3   | datetime | YES  |     | current_timestamp() | on update current_timestamp() |
     90+-------+----------+------+-----+---------------------+-------------------------------+
     91
     92MariaDB> INSERT INTO datetime_test (id) VALUES (1);
     93MariaDB> SELECT * FROM datetime_test;
     94+------+---------------------+------+---------------------+
     95| id   | dt1                 | dt2  | dt3                 |
     96+------+---------------------+------+---------------------+
     97|    1 | 2022-11-01 00:34:48 | NULL | 2022-11-01 00:34:48 |
     98+------+---------------------+------+---------------------+
     99
     100MariaDB> UPDATE datetime_test SET id = 2 WHERE id = 1;
     101MariaDB> SELECT * FROM datetime_test;
     102+------+---------------------+---------------------+---------------------+
     103| id   | dt1                 | dt2                 | dt3                 |
     104+------+---------------------+---------------------+---------------------+
     105|    2 | 2022-11-01 00:34:48 | 2022-11-01 00:41:16 | 2022-11-01 00:41:16 |
     106+------+---------------------+---------------------+---------------------+
     107}}}
     108
     109
     110=== 3. 저장 범위 ===
     111TIMESTAMP의 저장 가능한 시각은 UTC 기준 '1970-01-01 00:00:01' 부터 '2038-01-19 03:14:07' 까지다. 반면에 DATETIME은 '1000-01-01 00:00:00' 부터 '9999-12-31 23:59:59'까지 입력할 수 있다.
     112
     113DATETIME이 저장 가능한 값의 범위가 넓은 만큼 8바이트를 차지하는데 반해 TIMESTAMP는 4바이트를 차지한다.
     114== Time Zone 설정 ==
     115
     116=== mysql 데이터베이스의 Time Zone 테이블 ===
     117mysql 데이터베이스에는 다음과 같은 Time Zone 테이블이 있다.
     118
     119- time_zone
     120- time_zone_leap_second
     121- time_zone_name
     122- time_zone_transition
     123- time_zone_transition_type
     124
     125위 Time Zone 테이블은 생성은 되지만 실제 데이터는 입력되어 있지 않다. 여기에 데이터가 입력되어 있어야 {{{'Asia/Seoul'}}} 같은 시간대를 설정할 수 있다.
     126
     127데이터를 입력하지 않았을 때는 다음과 같은 오류가 발생한다.
     128{{{
     129MariaDB> set time_zone='Asia/Seoul';
     130ERROR 1298 (HY000): Unknown or incorrect time zone: 'Asia/Seoul'
     131}}}
     132
     133데이터를 입력하려면 다음과 같이 mysql_tzinfo_to_sql 명령을 이용한다.
     134{{{
     135# /usr/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql
     136}}}
     137
     138단 윈도우를 사용할 때는 mysql_tzinfo_to_sql 명령을 사용할 수 없기 때문에 다른 서버에서 데이터를 백업받아와서 복원해야 한다.
     139
     140
     141=== 디폴트 시간대 설정 ===
     142time_zone 시스템 변수로 시간대를 설정한다.
     143
     144시간대는 다음과 같은 형식으로 지정할 수 있다.
     145
     146- UTC로부터의 오프셋. 예를 들어 '+9:00'
     147- mysql 데이터베이스의 Time Zone 테이블에 데이터가 있을 때는 {{{'Asia/Seoul'}}}과 같은 형식으로 time_zone 변수를 지정할 수 있다.
     148
     149
     150글로벌 time_zone 변수를 지정하는 방법은 다음과 같다. mysql.time_zone_name 테이블을 참조하면 지정할 수 있는 time_zone 이름을 알 수 있다.
     151{{{
     152[mariadb]
     153...
     154default_time_zone = 'Asia/Seoul'
     155}}}
     156
     157mysql 데이터베이스의 Time Zone 테이블에 데이터가 없어도 다음과 같이 지정할 수는 있다.
     158{{{
     159[mariadb]
     160...
     161default_time_zone = '+9:00'
     162}}}
     163
     164systemd에서 쓰지 않는 리눅스 시스템에서는 mysqld_safe로 MariaDB를 구동하므로 [mysqld_safe] 항목에 지정해주면 된다.
     165{{{
     166[mysqld_safe]
     167timezone = 'Asia/Seoul'
     168}}}
     169
     170글로벌 time_zone 변수를 조회하려면 다음과 같이 한다.
     171{{{
     172MariaDB> SHOW GLOBAL VARIABLES LIKE 'time_zone';
     173+---------------+--------+
     174| Variable_name | Value  |
     175+---------------+--------+
     176| time_zone     | SYSTEM |
     177+---------------+--------+
     178}}}
     179
     180글로벌 time_zone 변수가 SYSTEM인 경우 system_time_zone 시스템 변수에 정의된 시간대를 대신 사용한다는 뜻이므로 다음과 같이 system_time_zone 시스템 변수를 찾아봐야 한다.
     181{{{
     182MariaDB> SHOW GLOBAL VARIABLES LIKE 'system_time_zone';
     183+------------------+-------+
     184| Variable_name    | Value |
     185+------------------+-------+
     186| system_time_zone | KST   |
     187+------------------+-------+
     188}}}
     189위 예에서는 시간대 설정으로 'KST'를 사용한다는 것인데 MariaDB는 'KST'라는 시간대를 이해하지 못한다.
     190
     191=== 세션의 시간대 설정 ===
     192따로 지정하지 않으면 세션의 시간대는 글로벌 time_zone 시스템 변수 값을 상속한다. 그러나 time_zone 시스템 변수를 바꿔 세션마다 시간대를 다르게 지정할 수 있다.
     193
     194다음과 같이 바꾸면 된다.
     195{{{
     196MariaDB> SET time_zone = 'Asia/Seoul';
     197}}}
     198
     199현재 세션의 시간대는 다음과 같이 확인할 수 있다.
     200{{{
     201MariaDB> SHOW VARIABLES LIKE 'time_zone';
     202+---------------+------------+
     203| Variable_name | Value      |
     204+---------------+------------+
     205| time_zone     | Asia/Seoul |
     206+---------------+------------+
     207}}}
     208
     209
     210=== JDBC 시간대 오류 ===
     211JDBC로 MariaDB에 접속하면 다음과 같은 오류가 나온다. KST라는 시간대를 인식하지 못한다는 뜻이다.
     212{{{
     213### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException:
     214  Failed to obtain JDBC Connection; nested exception is java.sql.SQLException:
     215  Cannot create PoolableConnectionFactory (The server time zone value KST is unrecognized or represents more than one time zone.
     216  You must configure either the server or JDBC driver (via the serverTimezone configuration property)
     217  to use a more specifc time zone value if you want to utilize time zone support.)
     218}}}
     219
     220
     221이 때는 위와 같이 설정하면 된다.
     222
     223----
     224[WikiStart 처음으로]