audit_log의 advisory lock과 UPDATE 순서가 만드는 새로운 데드락 창
機械翻訳 / Machine-translated
機械翻訳 / Machine-translated
변조 감지용 hash chain을 직렬화하는 advisory lock은 commit까지 유지된다. ads UPDATE 직후에 감사 INSERT를 끼워 넣는 구성에서는, 다른 트랜잭션의 행 잠금과 교차하는 순간 40P01 데드락이 발생한다. 해결 방법은 감사 쓰기를 모든 UPDATE 뒤로 하나로 모으는 것이다.
변조 감지용 hash chain을 하나로 직렬화하는 advisory lock은 트랜잭션의 commit까지 유지된다. audit_log의 BEFORE INSERT 트리거(migration 0003)는 병렬 INSERT 충돌을 피하기 위해 pg_advisory_xact_lock(hashtext('audit_log')::bigint)를 획득하고, 해당 트랜잭션이 끝날 때까지 해제하지 않는 설계로 되어 있다. 한편, portal 배신 반영 처리(applyPartnerDelivery)는 배신 대상에서 제외되거나 복귀한 광고의 감사 기록을 "ads UPDATE → 감사 INSERT(advisory lock 획득) → 다음 placement의 ads UPDATE"라는 순서로, placement마다 여러 번 끼워 넣고 있었다. 이 처리가 운영 화면의 광고 일시 정지 조작(이것도 "ads UPDATE → 감사 INSERT"라는 동일한 형태의 처리)과 병렬로 실행되어, 서로 먼저 업데이트한 행을 나중에 요구하는 순서가 되면, advisory lock을 획득한 측이 상대방의 행 잠금을 기다리고 상대방은 advisory lock의 해제를 기다리는 순환이 생겨, PostgreSQL이 40P01(deadlock detected)을 감지하고 한쪽을 강제 종료시키고 있었다. 해결 방법은 감사 INSERT 호출을 대상 행 UPDATE가 모두 끝난 뒤로 하나로 집약하는 것이다.
절차에 대한 자세한 설명·확인 방법·자주 묻는 질문은 원본 글에 정리되어 있습니다.
→ audit_log의 advisory lock과 UPDATE 순서가 만드는 새로운 데드락 창|Rebounder Tech Blog