[TIL] Primary key duplicate 오류 23.08.18

이상훈·2023년 8월 18일
0

[내일배움캠프]

목록 보기
54/68

결제기능과 워크스페이스 멤버십기능을 구현하던 중 멤버십 결제를 진행하면 워크스페이스의 PK 중복 오류가 발생하였음

QueryFailedError: ER_DUP_ENTRY: Duplicate entry '5' for key 'workspaces.PRIMARY'
  query: 'INSERT INTO `workspaces`(`id`, `name`, `type`, `description`, `created_at`, `updated_at`, `user_id`, `membership_id`) VALUES (?, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)',
  parameters: [ '5' ],
  driverError: Error: ER_DUP_ENTRY: Duplicate entry '5' for key 'workspaces.PRIMARY'
      {
    code: 'ER_DUP_ENTRY',
    errno: 1062,
    sqlMessage: "Duplicate entry '5' for key 'workspaces.PRIMARY'",
    sqlState: '23000',
    index: 0,
    sql: "INSERT INTO `workspaces`(`id`, `name`, `type`, `description`, `created_at`, `updated_at`, `user_id`, `membership_id`) VALUES ('5', DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)"
  },
  code: 'ER_DUP_ENTRY',
  errno: 1062,
  sqlMessage: "Duplicate entry '5' for key 'workspaces.PRIMARY'",
  sqlState: '23000',
  index: 0,
  sql: "INSERT INTO `workspaces`(`id`, `name`, `type`, `description`, `created_at`, `updated_at`, `user_id`, `membership_id`) VALUES ('5', DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)"
}

초기에는 membership과 workspace의 관계를 1:1로 설정해주었는데 콘솔을 찍어가며 확인해보니 workspace의 membership_id를 업데이트를 해주려는 과정에서 충돌이 일어났던 것으로 추정되었음

const membership = await this.membershipService.createMembership(body, workspaceId);

const findWorkspace = await this.workspaceService.getWorkspaceDetail(workspaceId);

findWorkspace.membership = membership.id
await transactionEntityManager.save(findWorkspace);

원래는 워크스페이스 생성 시 membership_id가 null값이어서 membership이 생성이 되면 업데이트를 해주는 구조를 생각했었는데, 해당 코드를 주석 처리 후 생성해보니 따로 업데이트를 해주지 않아도 membership_id가 업데이트 되는 것을 발견함

해당 코드를 살리고 실행해보면 똑같은 오류가 발생하는 것으로 보아, 이미 업데이트가 되어있는데 중복된 로직이 실행되어서 발생하는 에러인가? 싶었는데 관계 설정해두었던 CASCADE도 문제가 있는 것을 발견

@OneToOne(() => Membership, (membership) => membership.workspace, {
    onDelete: 'CASCADE',
    nullable: true,
  })
  @JoinColumn()
  membership: Membership;

@OneToOne(() => Workspace, (workspace) => workspace.membership, {
    // cascade: true,
    nullable: true,
  })
  workspace: Workspace;

아래의 cascade : true를 활성화 하면 같은 중복오류가 발생을 하였고, 주석 처리 후 실행했을때 정상적으로 생성이 되는 것 까지 확인.
결제 취소를 할 경우 membership_id로 해당 membership을 찾아 삭제하는 로직을 구성했는데 취소를 하게되면 워크스페이스와 워크스페이스 멤버까지 같이 삭제되는 현상을 발견하였음

이것저것 시도해보다 둘의 관계를 1:N으로 변경해도 문제가 없을 것 같아 변경한 뒤 실행해보니 이번엔 멤버십만 정상적으로 삭제되는 것을 확인

@OneToMany(() => Membership, (membership) => membership.workspace, {
    onDelete: 'CASCADE',
    nullable: true,
  })
  memberships: Membership[];

일단 얼렁뚱땅 해결하긴 했지만 정확한 이유를 모르겠어서 다음주에 튜터님에게 질문 후 원인 파악이 필요

profile
코린이

0개의 댓글