코드스쿼드 13주차 -4
Mysql 날짜 데이터 - Timestamp 와 Datetime
Datetime
1000-01-01 00:00:00
부터9999-12-31 23:59:59
까지 지원
Timestamp
1970-01-01 00:00:01
부터2038-01-19 03:14:07
까지 지원- Index가 더 빠르게 생성된다.
Datetime
과 Timestamp
의 차이는, Timestamp
는 DB에 설정 된 time_zone
환경변수를 기반으로 데이터가 변경된다는 점 이다. time_zone
설정에 의존하기 때문에 2011-08-21 14:11:09
라는 데이터가 Datetime
컬럼과, Timestamp
컬럼에 각각 저장되어 있는 상태에서
SET TIME_ZONE = "america/new_york";
Query OK, 0 rows affected (0.00 sec)
위와 같은 형태로 time_zone
설정을 변경해주면,
select * from datedemo;
+---------------------+---------------------+
| mydatetime | mytimestamp |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 04:41:09 |
+---------------------+---------------------+
1 row in set (0.00 sec)
timestamp
타입으로 설정한 데이터의 저장값이 변경된다.
Q. 위의 내용을 찾아보았을 때, Timestamp
가 지원하는 날짜가 얼마 남지 않았다는 점만 제외하면 유동적으로 대응할 수 있는 Timestamp
가 더 좋아보이고, Datetime
의 장점은 없는 것이 아닌가? 하는 의문이 들었다. 관련된 내용을 찾아 보았으나
해외 서비스를 제공하는 경우
Datetime
과Timestamp
를 적절히 섞어 사용하는 것이 좋다.
라는 내용을 보았을 뿐 속 시원히 해결되지 않았다.
A. 고민하던 중 Lee가 좋은 생각을 말씀해 주셨는데, 데이터가 작성된 위치(timezone
)와 시각이 데이터로 정확히 기록되어야 하는 경우 Datetime
을, timezone
에 따라서 저장된 데이터의 시간이 다르게 활용되는 경우에는 Timestamp
를 사용하지 않을까? 라는 내용을 말씀해 주셨다.
즉, DB의 timezone
설정이 변경된다면, Timestamp
형식은 처음 저장했던 데이터가 어느 지역에서, 어느 시간에 기록 됐는지 정확하게 파악할 방법이 없지만, Datetime
의 경우, 저장시점의 timezone
과 시간이 기록되므로, DB가 저장 된 서버의 timezone
설정이 변경 되거나, 외부 요인에 의해 변경 되더라도 데이터가 변경되지 않는다.
sns를 예로 들면,
한국에 사는 A
가 작성한 글을 보았을 때미국에 사는 친구 B
가 읽더라도1분 전 작성된 글 입니다.
라고 표시되길 원할 경우Timestamp
의 형태로 저장하면 편리할 것이고,- 해당 글이 서버 환경 설정에 영향을 받지 않고 언제나
한국에서, 1분 전 작성된 글 입니다.
라고 표시되길 원할 경우,Datetime
의 형태로 저장하면 좋을 것이다.
Timezone 설정의 우선순위
timezone 설정은, OS 수준에서의 설정, Mysql 자체 설정 변경, 접속하는 클라이언트 수준에서의 변경의 방법이 있다.
현재 테스트에 사용한 DB는 timezone
설정이 되어 있지 않은 상태이다.
DB 설정이 되어 있지 않은 경우, SYSTEM 환경 변수 설정을 따라가게 되어 있다. timezone
설정의 우선 순위는
- 클라이언트 수준에서의 설정
- DB 설정
- OS 설정
의 우선순위를 갖고 있다.
우리가 Java
코드에서 DB와 연결을 맺을 때 DB url을 입력하고 뒤에 붙는 serverTimezone 설정이 사용자 수준의 timezone
설정이다.
String url = "jdbc:mysql://localhost/testDB?serverTimezone=UTC";
프로젝트 중 발생한 문제들과 해결과정
외래키 Contraint 설정 바꾸기
외래키 설정 에러
테이블을 만드는 과정에서 아래와 같은 에러가 났다.
foreign key
의 제약조건을 만족하지 않았을 경우 생기는 에러라고 한다. user
테이블의 primary key
를 id
와 nickname
2개로 설정하였기 때문에 발생 하였는데
DB에서 테이블은 오직 하나의 기본키(PK)를 가질 수 있다.
라는 것이 정확한 정의라고 한다. 포인트는 이 문장을 PK를 오직 하나의 컬럼만으로 설정할 수 있다고 해석하면 안된다는 점이다.
위 테이블에서 PK로 설정된 id
, nickname
는 두 컬럼을 합쳐서 봤을 때 중복이 아니라면 데이터가 입력될 수 있다. 예를 들자면,
PK의 속성으로
id
와nickname
두 컬럼이 있다면
- [ id = 1, nickname = 1 ]
- [ id = 1, nickname = 2 ] 는 중복된 데이터가 아니기 때문에 정상적으로 저장이 된다.
즉, 복합키(Composite Key)를 만드는 것이지 기본키(PK)가 복수가 되는 것이 아니라는 것이다.
외래키는 유일한 데이터 하나만을 참조해야 하는데, 외래키는 user의 nickname
으로만 참조한다고 설정해 버리면 nickname
컬럼에는 중복 된 값이 존재할 수 있기 때문에 외래키 제약조건을 추가하지 못하는 에러가 발생한 것이다.
## 추가로,
user
테이블에서 기본키를 id
와 nickname
2개로 복합키로 만드는 것 또한 처음 의도했던 바와 다른 구조로 만들었음을 알게 되었다.
처음 생각으로는 사용자는 id
와 마찬가지로 nickname
도 유일한 1개의 값만을 가져야 하기 때문에 nickname
도 유일한 값으로 설정되어야 한다고 생각하여 기본키로 설정하였지만, 기본키를 2개로 지정하면 위의 예시와 같이, 복합키로 설정되게 되고
이는 id
는 동일, nickname
만 다른경우 혹은 nickname
은 동일, id
만 다른경우 DB는 중복된 값이 아니라고 판단하여 데이터 저장이 가능하게 된다.
따라서 id
는 primary key
로 설정하고, nickname
은 unique key
로 설정하는 것으로 변경하였다.
## Primary Key 와 Unique Key
1. PRIMARY KEY
유일한 레코드를 만들려면 다른 칼럼과 구별하고자 특별한 속성을 설정해야 한다.
이럴 때 사용하는 것이 기본 키 PRIMARY KEY 이다.
기본 키는 다음과 같은 특징을 갖는다.
- 값이 중복되지 않는다.
- 반드시 값을 입력해야 한다. (Null값이 올 수 없다)
- 테이블 데이터의 고유 인식번호 (id)
2. UNIQUE KEY
고유 키는 다음과 같은 특징을 갖는다.
- 값이 중복되지 않는다.
- 값을 입력하지 않아도 된다. (Null값을 허용)
- 중복되면 안되는 데이터 (주민등록번호, 이메일 주소 등)
테이블 생성 시 warning 에러
위의 문제를 해결한 후, task
테이블 생성 쿼리를 날려 테이블은 생성 되었으나 warning이 발생했다.
SHOW WARNINGS;
쿼리를 날리면 발생한 경고를 확인할 수 있는데,
mysql 8.0.17 버전부터 int datatype의 width를 설정하는 것을 더이상 지원하지 않고 향후 버전부터 제거될 기능 중 하나이기 때문에 발생하는 경고라고 한다.
- 참조 :
- https://velog.io/@taelee/mysql%EC%97%90%EC%84%9C-9%EC%8B%9C%EA%B0%84-%EC%B0%A8%EC%9D%B4%EB%82%A0%EB%95%8CGCP
- https://nesoy.github.io/articles/2020-02/mysql-datetime-timestamp
- https://luran.me/367
- https://hoon93.tistory.com/57
- https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=writer0713&logNo=220837177362
Author And Source
이 문제에 관하여(코드스쿼드 13주차 -4), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kyu/코드스쿼드-13주차-4저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)