본문 바로가기
Projects/OpenRoadmaps

[OpenRoadmaps] 블로그 카테고리 Unique Constraint 오류 해결

by DevJaewoo 2023. 2. 6.
반응형

Intro

웹사이트 개발 중 아래와 같이 카테고리가 생성되지 않는 버그가 발생했다.

찾아보니 다른 사용자가 같은 이름의 카테고리를 생성했을 경우 발생하는 문제로,

문제 발생

 

@UniqueConstraintnameclient_id를 같이 묶어줬어야 했는데 name으로만 묶어줘서 발생한 것이었다.

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(uniqueConstraints = {
        @UniqueConstraint(name = "unique_category_name", columnNames = {"name"}),
})
public class Category extends BaseTimeEntity {
    ...
}

 

columnNames"client_id"를 추가하고 로컬 환경에서 다시 돌려보니 잘 돌아가서, 개발서버 배포를 진행했다.


문제 상황

근데 진짜 문제가 발생했다.

로컬에서 문제가 해결된걸 확인하고 배포했는데, 개발 서버에선 문제가 해결되지 않고 그대로였던 것이다.

 

서버 로그를 찍어보니 unique_category_name 제약조건을 위반했다고 되어있었다.

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "unique_category_name"
  Detail: Key (name)=(Docker) already exists.
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675) ~[postgresql-42.3.7.jar!/:42.3.7]
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365) ~[postgresql-42.3.7.jar!/:42.3.7]
        ...

 

아래 사이트를 참고해 Constraint 목록을 조회해봤더니,

https://dba.stackexchange.com/questions/214863/how-to-list-all-constraints-of-a-table-in-postgresql

 

How to list all constraints of a table in PostgreSQL?

How to list all constraints (Primary key, check, unique mutual exclusive, ..) of a table in PostgreSQL?

dba.stackexchange.com

SELECT con.oid, con.conname, con.conkey, con.confkey
       FROM pg_catalog.pg_constraint con
            INNER JOIN pg_catalog.pg_class rel
                       ON rel.oid = con.conrelid
            INNER JOIN pg_catalog.pg_namespace nsp
                       ON nsp.oid = connamespace
       WHERE rel.relname = 'category';

 

이전 개발 과정에서 걸어놨던 제약조건들이 그대로 남아있는것을 볼 수 있었다.

conkey의 숫자는 column 번호를 의미한다.

  oid  |           conname           | conkey | confkey 
-------+-----------------------------+--------+---------
 24912 | category_pkey               | {1}    | 
 24976 | unique_category_name        | {4}    | 
 24983 | fkk8ce44g9yg9j1ibs1ibei1ia6 | {5}    | {1}
 33110 | unique_category             | {4,5}  | 
(4 rows)

 

로컬 서버는 ddl-autocreate로 해줘서 서버가 실행될 때마다 이전의 제약조건들이 초기화된 반면, 개발서버는 update로 되어있어 Constraint 이름이 바뀔 경우 이전 constraint가 그대로 남아있던 것이었다.

 

아래 명령어를 통해 남아있던 제약조건을 지우고 다시 해보니 정상적으로 작동했다.

ALTER TABLE category DROP CONSTRAINT unique_category_name;
ALTER TABLE category DROP CONSTRAINT fkk8ce44g9yg9j1ibs1ibei1ia6;

문제 해결

 

ddl-auto =update가 현재 DB의 데이터를 건드리지 않으면서 column이나 제약조건을 추가해 주는줄로만 알았는데, 이런 이슈가 발생할 것이라곤 생각하지 못했다.

괜히 운영 서버에는 update를 쓰지 말라는게 아니었다는 생각이 들었다.

반응형