Post

[Real MySQL 8.0 2] 15.3 데이터 타입 - 날짜와 시간

[Real MySQL 8.0 2] 15.3 데이터 타입 - 날짜와 시간

MySQL에서는 날짜만 저장하거나 시간만 따로 저장할 수도 있으며, 날짜와 시간을 합쳐서 하나의 컬럼에 저장할 수 있게 여러 가지 타입을 지원한다.


1. 날짜와 시간 데이터 타입


날짜와 시간 데이터 타입의 종류는 아래 표와 같다.

데이터 타입MySQL 5.6.4 이전MySQL 5.6.4 이후
YEAR1 바이트1 바이트
DATE3 바이트3 바이트
TIME3 바이트3 바이트 + (밀리초 단위 저장 공간)
DATETIME8 바이트5 바이트 + (밀리초 단위 저장 공간)
TIMESTAMP4 바이트4 바이트 + (밀리초 단위 저장 공간)
  • YEAR 타입은 1 바이트인데 1901부터 2155까지 표현 가능하다.(+0000)
  • DATE 타입은 3 바이트인데 1000-01-01부터 9999-12-31까지 표현 가능하다.
  • TIME 타입은 3 바이트인데 -838:59:59부터 838:59:59까지 표현 가능하다.
  • DATETIME 타입은 5 바이트인데 1000-01-01 00:00:00부터 9999-12-31 23:59:59까지 표현 가능하다.
  • TIMESTAMP 타입은 4 바이트인데 1970-01-01 00:00:01부터 2038-01-19 03:14:07까지 표현 가능하다. 1970-01-01 00:00:01부터의 초 단위를 세다보니 4바이트 크기에서 2038-01-19 03:14:07까지가 한계인데(대략 21억 초 -> 4바이트 int형 상한) 이게 유명한 2038년 문제 이다.


밀리초 단위 자릿수저장 공간
없음0 바이트
1, 21 바이트
3, 42 바이트
5, 63 바이트

밀리초 단위로 데이터를 저장하기 위해서는 DATETIME이나 TIME, TIMESTAMP 타입 뒤에 괄호와 함께 숫자를 표기하면 된다. NOW() 함수를 이용해 현재 시간을 가져올 때도 NOW(6) 또는 NOW(3)과 같이 가져올 밀리초의 자릿수를 명시해야하며 그렇지 않으면 NOW(0)으로 실행된다.


2. 타임존


MySQL의 날짜 타입은 컬럼 자체에 타임존 정보가 저장되지 않으므로 DATETIME이나 DATE 타입은 현재 DBMS 커넥션의 타임존과 관계없이 클라이언트로부터 입력된 값을 그대로 저장하고 조회할 때도 변환 없이 그대로 출력한다. 하지만 TIMESTAMP는 항상 UTC 타임존으로 저장되므로 타임존이 달려져도 값이 자동으로 보정된다.


아래는 타임존에 대한 간단한 예제로 타임존을 한국으로 설정하고 현재 시각을 저장했다.

1
2
3
4
5
CREATE TABLE tb_timezone (fd_datetime DATETIME, fd_timestamp TIMESTAMP);

SET time_zone='Asia/Seoul';  # +09:00

INSERT INTO tb_timezone VALUES (NOW(), NOW());


테이블을 조회하면 두 컬럼 모두 현재 시각이 동일하게 출력되는 것을 볼 수 있다.

1
2
3
4
5
6
SELECT * FROM tb_timezone;
+---------------------+---------------------+
| fd_datetime         | fd_timestamp        |
+---------------------+---------------------+
| 2025-12-29 11:12:39 | 2025-12-29 11:12:39 |
+---------------------+---------------------+


여기서 타임존을 미국의 로스앤젤레스로 변경하고 다시 테이블을 조회하면 DATETIME 타입을 사용할 경우 동일하게 출력되지만 TIMESTAMP 타입을 사용할 경우 보정이 되는 것을 볼 수 있다.(교재는 9월 기준이라 썸머타임이 적용돼서 시차가 16시간인데 12월 현재는 썸머타임이 적용이 안돼서 시차가 17시간인 것으로 보인다.)

1
2
3
4
5
6
7
8
SET time_zone='America/Los_Angeles';  # -08:00

SELECT * FROM tb_timezone;
+---------------------+---------------------+
| fd_datetime         | fd_timestamp        |
+---------------------+---------------------+
| 2025-12-29 11:12:39 | 2025-12-28 18:12:39 |
+---------------------+---------------------+


아래 쿼리로 MySQL 서버의 기본 타임존을 확인해볼 수 있다. system_time_zone 시스템 변수는 MySQL 서버의 타임존을 의미하며, time_zone 시스템 변수는 MySQL 서버로 연결하는 모든 클라이언트 커넥션의 기본 타임존을 의미한다. system_time_zone는 일반적으로 운영체제의 타임존을 그대로 상속받는다. time_zone은 응용 프로그램 코드에 의해 다른 값으로 언제든지 변경될 수 있다. 현재 SYSTEM으로 표기된 것은 system_time_zone를 그대로 따라간다는 의미다.

1
2
3
4
5
6
7
SHOW VARIABLES LIKE '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | UTC    |
| time_zone        | SYSTEM |
+------------------+--------+


위와 같은 상태에서 별도의 타임존을 설정하지 않고 현재 시각을 삽입하는 쿼리와 조회하는 쿼리를 작성하면 아래와 같이 출력된다. 요즘 응용 프로그램에서 코드 내부적으로 타임존 변환을 많이 지원해서 놓칠 수 있지만 타임존 관련 설정은 한 번 문제가 되기 시작하면 해결하기 매우 어려운 문제가 될 수 있어서 타임존 변환이 기대하는 대로 잘 변환되는지 테스트해보자.

1
2
3
4
5
6
7
8
INSERT INTO tb_timezone VALUES (NOW(), NOW());

SELECT * FROM tb_timezone;
+---------------------+---------------------+
| fd_datetime         | fd_timestamp        |
+---------------------+---------------------+
| 2025-12-29 02:37:19 | 2025-12-29 02:37:19 |
+---------------------+---------------------+

Ref


  • Real MySQL 8.0 2 - p.389 ~ p.396

This post is licensed under CC BY 4.0 by the author.