🤯 문제 상황
운영에서 insert 쿼리에 timestamp 컬럼에 NULL 을 넣지만, not null 타입이라 cannot be null 에러가 발생했다.
언뜻보면 당연한 결과인 것 같지만, 인프라 이관 작업에서 발생한 이슈라는 점에서 봤을때 잘 동작하는 코드가 환경이 변해서 에러가 발생하는 상황인 것이다.
따라서 환경에 따른 문제인 것으로 보여서, 이를 힌트로 잡고 문제를 찾아 나갔다.
👨⚕️ 원인 분석
- 인프라 이관 전 환경에서 에러 flow를 따라 동일하게 실행 (MySQL 5.7)
→ 정상 동작 - 인프라 이관 후 환경에서 동일하게 실행 (MySQL 5.7)
→ 에러 발생
INSERT INTO BSI_BENEFIT_BASES ( ... , CREATION_DATE , LAST_UPDATE_DATE ) VALUES ( ... , CURRENT_TIMESTAMP() , null ) - Local MySQL에서 insert 쿼리 동일하게 실행 (MySQL 8.0)
→ 동일하기 cannot be null 에러 발생
위 단계만으로는 원인을 알기 어려워 DBA 분께 문의 넣었다.
################ DBA와의 대화 넣기
DBA 답변
두 DB 상에서 explicit_defaults_for_timestamp 변수 값이 다르네요. 오류가 안나는 곳은 값이 OFF이고, 오류가 나는 곳은 ON입니다. mysql 서버 버전이 5.7.12 → 5.7.40으로 변경하며 변수 기본값이 다른 것 같습니다.
https://minsql.com/mysql/MySQL-explicit_defaults_for_timestamp/

라고 하시며 친절히 설명 블로그와 사진까지 보내주셨다.
정리하자면, 이전 환경(MySQL 5.7.12)에서는 OFF가 기본값으로 설정되어 있어서 NULL을 insert 하면 current timestamp가 입력된다.
이관된 후 환경(MySQL 5.7.40)에서는 기본값이 ON으로 설정되어 NULL을 똑같이 입력하더라도 에러가 발생하는 것이다.
여기서 한가지 의문이 생긴다.
왜 Local MySQL(8.0)에서는 안됐을까?
찾아보니, 5.7.40 버전과 동일하게 8.0에서는 기본값이 ON으로 설정되어 있다. [공식 문서]
MySQL 8.0 문서에서는 8.0부터 해당 변수의 default값이 변경 되었다고 나와있다. 아마 인프리 이관하면서 해당 변수 설정이 누락되지 않았나 예상한다.
🔏 해결방법
해결방법은 매우 간단하다. explicit_defaults_for_timestamp 변수 값을 OFF로 설정해 주거나, mysql 설정에 의존하지 않고 CURRENT_TIMESTAMP() 를 넣어주도록 쿼리를 수정하면 된다.
나는 DB 버전에 따른 기본값 설정을 따라가는 쿼리는 좋지 않다고 느꼈다. 시간이 지나면 DB 버전은 올리게 될 것이고, 버전 업그레이드에 따른 리스크를 안고 가고 싶지는 않았다. 따라서 쿼리에 default 값을 직접 명시해주는 방법을 선택하였다.
'MySQL' 카테고리의 다른 글
| MySQL의 collation이라는 마법 (1) | 2023.06.06 |
|---|