✏️ 발단
팀프로젝트를 진행하던 중 서버가 재시작 될 때 특정 table 에서 ddl-auto: create
옵션이 적용되지 않고,
data 가 그대로 남아있는 문제가 발생했다.
이상한 점은 init data 를 종료하고 실행해봐도,
모든 Table 이 초기화 되었지만 특정 table 에서만 data 가 그대로 남아있는다는 점이다..
✏️ 원인 파악
- 문제의 정확한 원인을 파악하기 위해서 서버를 재시작 할 때 발생되는 query 문을 console 에서 확인해봤다.
- 확인 결과 아래와 같은 오류가 발생하며 특정 table 에 대한 query 문 발송을 건너뛰어 data 가 지워지지않고 누적된것이다.
CommandAcceptanceException: Error executing DDL
📍 첫번째 시도 - 필드명중 Db 약어가 포함된 경우
⚠️ 실패
- 하지만 필드명에 문제는 없었다.
- 이틀전 까지만해도 정상적으로 작동됬었고, 처음 프로젝트를 시작할 때부터 지금까지 필드명이 변경되지 않았기 때문
📍 두번째 시도 - Requestmapping 속성 변경
- 현재 data 가 초기화 되지 않는 테이블이 2개가 있는데 이 두 테이블은 매핑테이블이라는 공통점이 있다.
- mapping table 외의 모든 table 은 정상적으로 작동된다.
- mapping table Entity 의 이름은 mapping 하고 있는 각각 의 Entitry 명을 합친 형태인데,
카멜케이스를 적용해서 작업하고있었다.
Study -< StudyRule >- Rule
- StudyRule 의 Controller 계층에서
@RequestMapping
의 url 을 기존에는 카멜케이스 그대로 채택해서 사용하고 있었는데
- 프로젝트 중간에 스네이크 케이스로 변경하기로 했었다.
@RequestMapping("/studyRule")
@RequestMapping("/study_rule")
- 솔직히 이건 Url 에 관련된 부분이고, DB 와는 전혀 관련이 없는 부분인것 같지만,
이 것 말고는 딱히 원인이 생각나지 않아서 수정해보았다.
⚠️ 실패
- StudyRule 말고 MyStudy 는 Controller 를 구현하지 않았다.
- 즉 스네이크 케이스로 변경할 mapping 정보도 없다는 뜻이다.
📍 세번째 시도 - Entity 명과 Table 명 매핑이 틀어진 경우
CommandAcceptanceException: Error executing DDL
- 조사결과 db 약어를 사용했을 경우 뿐만 아니라 모든 이유를 통틀어 query 전송이 불가할 경우 발생되는 exception 이라고 한다.
- 혹시 Entity 와 Table 의 mapping 이 작업중에 변경된게 아닐가? 생각해서 직접 table 에 매핑시켜 보기로했다.
@Table(name = "my_study")
@Entity
@Getter
@AllArgsConstructor
@Builder(toBuilder = true)
@NoArgsConstructor(access = PROTECTED)
@EntityListeners(AuditingEntityListener.class)
public class MyStudy {
⚠️ 실패
- 당연히 실패했고, 이 가설이 원인이였다면 모든 Table 에서 매핑이 불가능하게 되는게 맞다.
- 지금은 특정 table 만 문제가 발생했기 때문에 이것도 원인이 아니다.
📍 네번째 시도 - 해당 테이블에 대한 권한이 없는경우
CommandAcceptanceException
만으로는 더이상 알아낼 수 있는 정보가 없는것 같아서 root cause 를 살펴봤다.
SQLSyntaxErrorException:
Can't DROP 'FKdfocui7jkkvoc86dt530qucij';
check that column/key exists
- 해당 메시지에서는 Drop 하려는 column 또는 key 가 존재하는지 확인해보라고 한다.
- 이 메시지를 알아보니 해당 table 에 FK 에 문제가 있어서 발생된 현상이라고 한다.
- 해결을 위해서 FK 를 삭제하면 정상적으로작동된다고한다.
⚠️ 실패
- 아래 SQL 문을 사용해 FK 를 drop 하고 ddl-auto 의 create 속성으로 서버를 재시작해 원상복귀 시키려고 계획을 세웠다.
ALTER TABLE {entity 명}
DROP FOREIGN KEY {FK 명};하
- SQL 문 실행 결과 똑같은 에러메시지가 출력되며 삭제에 실패했다.
📍 다섯번째 시도 - 문제가 있는 table 에 특정 FK 가 존재하지 않는경우
- 문제를 해결하며 얻었던 정보들을 다시 살펴보던중 의심될만한 원인을 찾아냈다.
- 설계단계에서 계획했던 table 중 실제로 개발을 하다보니 별도의 table 로 만들만큼 역할이 크지 않아서 삭제한 table 이 있었다.
- DB 엔 별도에 처리를 하지 않고 java 파일만 삭제했었다.
✏️ 문제 해결 - 성공
- 먼저 아래 sql 문으로 존재하는 모든 table 을 조회했다.
show tables;
- 역시 서버가 수십번 재시작 되었었음에도 불구하고 java 파일로 삭제했던 table 이 존재했다.
- 이 table 을 먼저 drop 해보니 정상적으로 table 이 삭제되었다.
- 이후 문제가 있는 talbe 도 drop 하니 정상적으로 삭제가 완료되었다.
- 이제 다시 서버를 재시작하니
create
가 정상적으로 작동되고,
이후부터 data 가 누적되었던 문제가 해결되었다.
📍 문제가 해결된 원인
create
옵션은 현재 존재하는 java 파일중 @Entity 어노테이션이 선언된 객체를 기준으로 SQL 문이 실행된다.
- 이때 임의로 @Entity 가 선언된 java 파일을 삭제하면 해당 파일을 제외한 SQL 문이 실행되고,
DB 상에선 FK 로 묶여있기때문에 SQL 문 수행에 실패하는 것 같다.
- 즉,
craete
옵션은 db 를 초기화 하고 새로 세팅해주는 것이 아닌,
@Entity 가 선언된 객체에 대해서만 SQL 문을 작성해주는 기능을 하고있는 것이다.
📍 다른 해결방법
- 문제를 해결하고 동시에 문제를 해결했다는 소식을 들었다.
- 같은 원리로 문제를 해결했지만 방법은 약간 달랐다.
- database 자체를 삭제하고 다시 새로만든다음 서버를 시작하는 방법이다.
- 결국 java 코드상의 entity 와 실제 DB 의 table 의 싱크를 잘 맞춰줘야 하는다는 의미이다.