데이터베이스 참조관계 바꾸기

이승연·2021년 8월 5일
0

Backend Development

목록 보기
5/8
post-thumbnail

어쩔 수 없이 참조관계를 바꾸게 됐다. Payment와 Matching이라는 테이블이 있는데 payment의 matching이라는 필드가 Matching 테이블을 참조한다.구독모델이 새로 생기는데 결제를 하면 횟수에 따라 matching이 n개 생겨야한다. 따라서 Matching 테이블이 Payment를 참조해야한다.

양쪽에서 참조관계를 만들거나 테이블 이름과 동일하게 필드 이름을 지정하면 circular dependency가 생기기 때문에 그렇게 하면 안된다.

데이터베이스 변경 전략

(1) Payment의 matching 필드 데이터 기록해두기

  • 쿼리 돌려서 완료

(2) Matching에 payment 필드 우선 integerfield로 만들어서 migrate하고 데이터 기록해두기

  • models.py의 Matching 모델에 payment_temp = models.IntegerField(null=True) 추가
  • 처음에는 payment로 했는데 다음과 같은 에러가 나와서 payment_temp로 바꿈. ORM으로 참조하게 될 때 생길 문제를 방지하기 위함인듯:

    service.Payment.matching: (fields.E303) Reverse query name for 'service.Payment.matching' clashes with field name 'service.Matching.payment'.
    HINT: Rename field 'service.Matching.payment', or add/change a related_name argument to the definition for field 'service.Payment.matching'.

  • 이렇게 했는데 이제 저번에 했던 Migration 결과 중 데이터베이스에는 적용되어있지만 migraion history에는 적용 안되어있던게 있었다. 그래서 django.db.utils.ProgrammingError: column "code" of relation "coupon_couponbatch" does not exist이라는 에러가 났고 페이크로 migrate해서 해결. 보니까 실 디비를 건들지는 않고 migration file만 업데이트 된다. 이렇게 하고 내가 원하는 것만 진짜 migrate하니까 성공.
  • payment_temp 데이터도 잘 박아둠.

(3) Payment의 matching 필드 삭제하기!

  • 이건 가뿐하게 성공

(4) Matching의 payment 필드 fk로 바꾸기

  • 자 이게 그렇게 쉬울리가 없지. 뭐라고 나왔는지 보자:

    django.db.utils.IntegrityError: insert or update on table "service_matching" violates foreign key constraint "service_matching_payment_temp_id_edbf67d3_fk_service_payment_id

  • 내가 matching 테이블에서 뭘 바꾸려고 하니까 fk constraint를 침해한다고 하는데..이게 사실 내 실수다. matching과 payment가 웬만하면 같이 만들어지기 때문에 matching.id == payment.id라고 생각하고 그냥 일괄로 변경해버렸다. 그런데 알고보니 조금씩 다른게 있었다. payment에 들어가서 select id, matching_id from payment쿼리 날리고 matching_id를 가져다가 mathcing 테이블에서 찾자. 그리고 그 전 쿼리 결과의 id를 가져가서 그대로 적용시키자. 이런 작은 실수 때문에 이렇게 시간을 버리다니.

postgres migration 테이블에서 일어나는 일

  • 위의 (1)~(4) 스텝을 하나하나 거치고 난 후에는 각각의 migration 파일들이 만들어진다. 이런 migration 파일들을 정리하기 위해 (1)-(4)에 해당하는 migration 파일을 지우고 makemigrations를 다시 해서 통합 파일을 만든다. 이를 migrate 할 시에 지웠다고 해서 데이터베이스 migrations 테이블에 migration한 기록이 없어지는 것은 아니다. 다만, 우리 프로젝트에 있는 migration 파일의 dependency가 (1)~(4)의 스텝을 전혀 참조하고 있지 않기 때문에 데이터베이스 상에 남아있어도 문제가 되지 않는 것이다.

코드베이스 변경 전략

코드베이스:
1. serviceapplication에서 payment 만들때 matching 필드 생성 로직 지우기(?)
2. serviceapplication에서 matching 필드 생성 후에 payment에 엮기
3. 새로운 구독모델 보고 로직 짜기

서버환경별 적용 순서

1. 실데이터 덤프 떠서 로컬과 실디비 싱크 맞추기
2. 데이터베이스 변경 해보기
3. migration 파일 지워서 initial만 --fake로 migrate했을 때 문제없는지 보기
4. 코드 베이스랑 합 맞춰봤을 때 잘 되는지 보기
5. 테스트 서버에 동일하게 적용해보기
6. 실서버에 적용

end result: migration file이 다 동일해야함

backup plan:
1. 브랜치 하나 파서 현재 형상 그대로 저장
2. 데이터베이스 덤프

0개의 댓글