반응형
오라클 PL/SQL 에러 - PLS-00183 발생
운영 중인 배치 프로그램에 다른 데이터베이스에서 데이터를 가져와 업데이트하는 이런 쿼리가 있었습니다. 일배치로 실행되며 등록/수정/삭제된 데이터를 PL/SQL BEGIN ~ END 사이에서 insert, update, delete문으로 만드는 동적 쿼리가 MyBatis로 작성되어 있었습니다.
<update id="updateDataList">
BEGIN
<foreach collection="dataList" item="item">
UPDATE MY_TABLE
SET
COL1 = #{item.col1}
, COL2 = #{item.col2}
, COL3 = #{item.col3}
, COL4 = #{item.col4}
, COL5 = #{item.col5}
-- .... 이런식으로 13개
WHERE
COND1 = #{item.cond1}
AND COND2 = #{item.cond2};
</foreach>
END;
</update>
그런데 어느날 문득 데이터를 점검하다 보니 최종 실행된 일시가 무려 1년 전인 것을 발견했습니다. 매일 Gb 단위로 남는 로그파일을 샅샅히 뒤져보니 PLS-00183 라는 오류코드 단서를 찾을 수 있었습니다.
에러코드에 붙은 메시지를 읽어보면 무엇이 문제인지 단번에 유추할 수 있었습니다. 바인드 변수가 너무 많다는군요.
업데이트 요청에서 오류가 발생하였고, 데이터 건수를 조회해보니 4934건이었습니다. 바인딩 변수가 15개이므로
4934 * 15 = 74,010
PLS-00183 too many bind variables 발생 원인
명확하게 처리하기 위해 오라클에서 "PLS-00183" 에러코드를 확인해보았습니다.
바인딩하는 변수는 65535까지 허용한다고 합니다. 16비트입니다.
해결
다음과 같이 구글 guava 라이브러리에 포함된 Lists 유틸 클래스를 사용하여 리스트를 1000개씩 나누어 반복문으로 실행하였습니다.
// 수정 전
syncService.updateDataList(updateDataList);
// 수정 후
List<List<Tenant>> lists = Lists.partition(updateDataList, 1000);
for (List<Tenant> itr : lists) {
syncService.updateDataList(itr);
}
출처
이 오류 해결에는 아래 URL 자료를 참고하였습니다.
https://www.oraexcel.com/database-oracle-12cR2-PLS-00183/lang-ko
반응형