오체결 정정으로 정산에 이미 반영된 수수료를 되돌려야 하는지 판단해야 했다. trades.settlement_id 가 비어 있어서 미반영으로 끝내려다 멈췄다.
Table of contents
Open Table of contents
판단 기준 — 컬럼 하나가 배제하지 못하는 것
그 컬럼이 비어 있다는 것은 그 경로로 가지 않았다는 뜻이다. 다른 경로가 없다는 보장은 아무 데도 없었다.
두 가지 방법이 있었다. 그 컬럼 하나로 판정하고 끝내는 것과, information_schema.tables 에서 이름에 settlement 가 든 테이블을 열거해 경로 수를 먼저 세는 것이다. 뒤쪽을 골랐다. 이유는 정산 유형이 최근에 둘 늘어난 것을 알고 있어서다. 대신 조회가 세 배로 느는 것을 감수했다. 일정산과 조기 정산과 원장과 조기 정산의 체결 연결까지 넷이 나왔다.
원인 — 참조가 한 방향뿐이었다
settlements 에서 이 체결을 찾으려고 컬럼을 봤는데 체결을 가리키는 참조가 없었다. 정산 테이블은 정산 단위로 만들어져 있고 어느 체결에서 왔는지는 적혀 있지 않았다.
연결은 trades 쪽에서 정산을 가리키는 방향으로만 있었다. 한 방향뿐이면 이 정산에 이 체결이 들어갔냐는 질문을 정산 쪽에서 물을 수 없다.
검증 — 컬럼이 아닌 별도 테이블
그래서 trades 쪽에서 갈 수 있는 경로를 전부 찾았다. 일정산은 settlement_id 로, 추천 보상 정산은 reward_settlement_id 로 각각 컬럼으로 연결돼 있었다.
세 번째인 조기 정산은 컬럼이 아니라 별도 연결 테이블 early_settlement_trades 에 trade_id 로 들어 있었다. trades 레코드만 열어 보면 그 경로는 보이지 않는다.
조치 — 셋을 다 조회한 결과
세 경로를 각각 조회해 표로 만들었더니 settlement_id 와 reward_settlement_id 는 비어 있고 early_settlement_trades 에 행이 있었다. 이번 건이 조기 정산 유형이라 그 경로로 잡혀 있었다.
컬럼 하나만 보고 미반영이라고 판단했으면 이미 정산된 수수료를 다시 처리할 뻔했다. 판정 규칙을 셋 중 하나라도 값이나 행이 있으면 중단으로 정하고 절차에 적었다.
질문 하나에 답을 찾는 방법이 여럿
왜 이런 구조가 됐는지 git log 로 짐작해 보면 정산 방식이 하나씩 추가되면서 연결 방식도 그때마다 달라진 것으로 보인다. 처음에는 컬럼 하나였고 다음 유형에서 컬럼이 하나 더 붙었으며 세 번째는 다대다라 별도 테이블이 됐다.
각각은 그 시점에 합리적인 선택이었을 것이다. 문제는 이 체결이 정산됐냐는 질문 하나에 답을 찾는 방법이 셋이 됐다는 점이고 그러면 반드시 하나를 빠뜨린다.
정리
settlement_id하나가 비어 있다고 다른 경로가 배제되지 않는다- 관련 테이블을
information_schema로 열거해 경로 수를 먼저 센다 - 참조가 한 방향뿐이면 반대로 역추적할 수 없다
- 어떤 연결은 컬럼이 아니라
early_settlement_trades같은 별도 테이블에 있다 - 그런 경로는 레코드만 열어서는 보이지 않는다
- 판정 규칙을 세 경로 중 하나라도 있으면 중단으로 정한다
- 질문 하나에 답을 찾는 방법이 여럿이면 하나를 빠뜨린다
- 그래서 경로 목록을 조사 절차에 적어 둔다