프로젝트 중 배송상태가 변경되면 배송 주문이 자동으로 할당되는 기능을 테스트 하던 중이었다.
1000건의 배송 상태 변경에 따른 배송 주문 할당, 채팅 채널 생성, 배송 보험 가입의 프로시저의 시간을 비교하던 중,
자꾸 중복된 데이터가 입력되는것을 확인했다.
배송 주문 테이블에 데이터가 생성되면
SET selected_dv_order_id = last_insert_id();
해당 변수에 방금 생성된 데이터의 ID값을 넣고 그걸 참조해서 채팅 채널과 배송 보험을 생성하는 방식이었다.
모든 데이터가 중복으로 입력되는 것이 아니라 가끔 한번씩 정해진 데이터들만 중복으로 입력됐고,
도무지 공통점을 찾을 수 없었다.
그래서 해당 부분들을 트리거로 바꿔보니 또 중복된 데이터가 입력되지 않는것이었다.
동시성의 문제인가 싶어 트랜잭션을 나누어도 문제는 계속되었다.
그렇게 오랜시간 이것저것 바꿔보던 도중 문제점을 찾았는데 문제는 1000번의 프로시저를 실행시키는 테스트용 프로시저의 문제였다.
delimiter //
DROP PROCEDURE if EXISTS update_status;
CREATE PROCEDURE `update_status`(
IN `from_id` BIGINT,
IN `to_id` bigint
)
BEGIN
DECLARE current_id BIGINT DEFAULT from_id;
while current_id <= to_id do
UPDATE orders
SET order_status = '배송준비중'
WHERE order_id = current_id;
CALL insert_processing(current_id);
SET current_id = current_id + 1;
END while;
END//
delimiter ;
해당 프로시저는 시작점인 id값과 끝나는 지점인 id값을 변수로 받아서 반복적으로 실행하게 하는 기능을 하는데,
문제는 from_id와 to_id는 실제 쿼리에서 order_id가 들어가게 되는데 중간중간 존재하지 않는 order_id가 들어간다는 점이었다.
해당 부분이 문제의 쿼리 시작점인데, WHERE 문에 pm_order_id 가 존재하지 않는 값이라 SELECT문에 아무것도 조회되지 않고, 조회된 데이터를 바탕으로 실행되는 INSERT문이 실행되지 않으니 LAST_INSERT_ID()가 이전의 값 그대로 남아있는 것이다. 그로인해 중복된 값이 입력되었던 것이다.
따라서 해당 쿼리 앞부분에 변수로 들어온 order_id 값이 있는지 확인하는 쿼리를 추가해주었다.