← 전체 글로 돌아가기

웹 개발

관계형 데이터 중복 문제 운영 점검

데이터베이스에서 관계형 데이터가 중복될 때 원인을 찾고 해결하는 방법.

데이터베이스에서 관계형 데이터를 다루다 보면 중복이 생긴다. 같은 사용자의 프로필이 여러 개 있거나, 게시물이 중복되거나, 댓글 수가 실제보다 많이 나오는 경우들이다. 혼자 개발할수록 확인한 값과 바꾼 값을 따로 남기는 습관이 중요하다.

목표 명확히 하기

먼저 정확히 무엇이 중복되었는지 파악해야 한다. 같은 데이터가 몇 개인지, 왜 중복되었는지를 명확히 이해하지 않고는 삭제할 수 없다.

현재 상태 파악

로그를 먼저 확인하자. 언제부터 문제가 생겼는지, 어떤 작업 후에 증상이 나타났는지:

sudo journalctl -n 100 --since "2 days ago"

만약 마이그레이션을 실행한 후 문제가 생겼다면, 마이그레이션이 제대로 작동했는지 확인해야 한다.

설정 확인과 제약 조건

데이터베이스의 제약 조건을 확인해보자. 특히 UNIQUE 제약이 제대로 설정되어 있는지:

-- PostgreSQL
\d users

-- MySQL
DESCRIBE users;

만약 UNIQUE 제약이 없다면, 같은 데이터가 여러 개 들어올 수 있다는 뜻이다. 이 경우 응용 로직에서 중복을 방지해야 한다.

관계 테이블 검증

관계 테이블(예: user_post)에 중복된 행이 있는지 확인하자:

SELECT user_id, post_id, COUNT(*) as count
FROM user_posts
GROUP BY user_id, post_id
HAVING COUNT(*) > 1;

이 쿼리로 중복된 관계를 찾을 수 있다.

수정 전 백업

데이터를 수정하기 전에 반드시 백업을 떠야 한다:

pg_dump -U postgres mydb > backup.sql

만약 뭔가 잘못되면 이 백업으로 복구할 수 있다.

중복 제거 쿼리

실제로 중복을 제거할 때는 트랜잭션을 사용해서 천천히 진행하자:

BEGIN;

-- 중복 찾기
WITH ranked_duplicates AS (
  SELECT *,
    ROW_NUMBER() OVER (PARTITION BY user_id, post_id ORDER BY id) as rn
  FROM user_posts
)
DELETE FROM user_posts
WHERE id IN (SELECT id FROM ranked_duplicates WHERE rn > 1);

-- 결과 확인
SELECT COUNT(*) FROM user_posts;

COMMIT; -- 또는 ROLLBACK;

사용자 영향 확인

데이터를 수정한 후 실제로 사용자가 보는 화면이 제대로 나오는지 확인해야 한다:

  1. 게시물 개수가 맞게 나오는가?
  2. 사용자 프로필이 여러 개로 보이지는 않는가?
  3. 댓글 수나 좋아요 수가 정확한가?

재발 방지

중복이 다시 생기지 않도록 방지 조치를 취해야 한다:

  1. 데이터베이스에 UNIQUE 제약을 추가한다.
  2. 응용 로직에서 중복을 확인한다.
  3. 정기적으로 데이터 무결성을 점검한다.

작은 점검을 규칙적으로 하면 나중에 더 큰 문제를 피할 수 있다.