최근에 진행중인 프로젝트에서, upsert를 활용중에 이상한 문제를 직면했습니다
개략적인 프로세스는
위처럼 2종류의 크롤러가 각각 테이블 A, B에 데이터를 밀어넣는데, 이 데이터는 중복될 수도 있고 시간에 따라 업데이트가 됩니다.
이러한 구조를 위해 DB에서 upsert 쿼리를 사용하였는데, 쿼리는 아래와 같습니다.
INSERT INTO table_C (some_columns)
SELECT
some_columns
FROM (
SELECT
ROW_NUMBER() OVER(PARTITION BY unique_key ORDER BY column DESC) t,
c.*
from
table_A c
) a
where a.t<2
ON DUPLICATE KEY UPDATE some_update_keys;
위 쿼리는 테이블 A를 테이블 C에 upsert 하는 쿼리로, ROW_NUMBER를 활용해서 테이블 A의 unique_key라는 컬럼값이 동일한 그룹 중 column의 값이 가장 높은 row를 테이블 C에 최신화하는 쿼리입니다.
그런데 쿼리를 짜넣고 서버를 돌려보니 계속, A혹은 B테이블의 값이 서로 상관없어보이는 반대쪽 테이블의 변수를 덮어쓰는 현상이 발생했고, 이걸 잡겠다고 셀프조인도 써보고 참.. 쿼리를 계속 잡았는데...
알고보니 upsert되는 변수에 각 테이블에서 primary key로 활용되던 id 컬럼이 포함되어 있었고,
이때문에 서로 전혀 상관없어보이는(그리고 실제로도 상관 없이, 테이블 내에서 id값만 같을 뿐인) 데이터에 덮어씌워지는 현상이 발생하는 것이었고, 결국은 세 개의 테이블 모두에서 공통적으로 사용하는 컬럼을 unique key로 지정하여 해결했습니다.