mysql에서 timestamp 자료형이 있습니다. 이것은 datetime 이랑 비교해서 어떠한 차이점을 가질까요? 

 


 mydb에는 2개의 테이블이 있습니다. 하나는 dt, 다른 하나는 ts입니다. 각각 datetime과 timestamp를 저장합니다.

 

 

 ts와 dt에 현재 시간인 now()를 저장해 보겠습니다. 사실 이 함수는 CRUD를 구현할 때 상당히 많이 쓰는 것 중 하나가 됩니다. 예를 들어서, 게시판에서 글을 등록할 때도, 보통은 작성 날짜를 표시해 줍니다. 그러니, now와 같이 작성할 당시에 '시간'을 구해주는 것이 필요합니다.

 

 

 그리고 dt와 ts에 저장된 내용을 보니, 2020년 8월 30일 48분 17초, 48분 23초가 저장되어 있습니다.

 

 

 현재 system의 time zone을 보니, KST이군요. 이제 시간대를 바꿔 보겠습니다.

 


 timedatectl 명령어로 타임존을 바꿔 보겠습니다. 저는 London의 시간대로 바꾸었습니다. 다음에, mysql 서비스를 재시작 해 줍니다. 링크에서 언급된 내용을 보면, 서버가 시작되면 timezone을 결정하고 system_time_zone이라는 변수를 setting 한다고 되어 있습니다. 그래서, 타임존을 설정하고 mysql 서비스를 재시작 해 준 것입니다.

 

 

 그리고 다시 보면, datetime의 값은 변하지 않은 것 처럼 보이지만, timestamp는 8시간 전의 시간으로 변했음을 알 수 있습니다. 이는 타임존 설정이 바뀌었기 때문입니다. 변수들의 값을 출력해 보겠습니다.

 

 

 먼저, system_time_zone은 BST로 설정이 되어 있습니다. 이게 무엇인지는 잘 모르겠지만, 저는 timedatectl로 런던 시간으로만 설정을 했었습니다.

 

 

 그리고 session.time_zone이 SYSTEM입니다. 이 값에 대한 의미는 링크의 NOTE의 바로 윗 단락에 나와 있습니다. 만약에 이 값이 SYSTEM이라면 서버 타임 존과 시스템 타임 존이 같다는 말입니다.

 

 

 이제 현재 시간을 추가해 보도록 하겠습니다.

 

 

 그리고 조회를 해 보니, dm이나, tm에도 8월 29일 17:25분 데이터가 들어가 있습니다. 그런데 중요한 것은, 타임스탬프는 설정이 된 타임존 (예를 들어서 시스템의 타임존을 London으로 바꾼다던지) 과 관련이 있는 반면에, 위에 있는 datetime은 그렇지 않았다는 겁니다. 이것 역시, mysql의 Time zone support 문서에 나와 있습니다.

 

 그러면 이렇게 생각해도 될까요? 타임 스탬프는 기준 시간 (UTC)를 저장해 두고, 우리가 설정한 zone을 가지고 추가로 연산을 한다. 만약에 KST로 8월 29일 09:00:00을 저장했다면, UTC로는 8월 29일 00:00:00이므로, 이걸 db에 저장한다.

 

 

 다시 한국 시간대로 바꾼 다음에, 현재 시간을 dt와 ts 테이블에 추가합니다.

 

 

 그리고 dt에 있는 레코드들을 조회하면 8월 30일 데이터 2개와, 8월 29일, 8시간 늦은 시간이 저장되어 있음을 알 수 있습니다.

 


 또 다른 차이가 없을까요? 문서를 보면, 유독 눈에 띄는 문구가 있습니다. 2038년 1월 19일과 9999-12-31 23:59:59입니다. 2038년이라면, 2038년 문제와 연관이 있는데요. 이것은 4byte, 21억 문제와 연관이 있습니다. 

 

 실제로 dt에 2050년 1월 1일 00:00:00을 넣으면 잘 들어가지만, ts에 2050년 1월 1일 00:00:00을 넣으면 Incorrect datetime value가 뜸을 알 수 있습니다. 저게 잘못된 형식은 아닙니다. 왜냐하면 now()로 넣었을 때 yyyy-mm-dd hh:mm:ss로 들어갔고, 저도 2050년 1월 1일 00:00:00을 넣었을 때, yyyy-mm-dd hh:mm:ss로 넣었기 때문입니다.

 

 그럼에도, 저 에러가 뜬 것은 2050년 1월 1일 00:00:00이 2038년 1월 14일 3:14:07UTC 이후이기 때문입니다.