MySQL에서 useAffectedRows=true 옵션 사용 시 애플리케이션 기동 실패하는 이유

김상운(개발둥이)·2024년 11월 14일
0
post-thumbnail

MySQL useAffectedRows=true 옵션으로 Hibernate 애플리케이션 기동 실패한 썰

업무 중에 별거 아닌 설정 하나가 기동 장애라는 결과를 가져와, 기억할 겸 정리해둡니다. 혹시 저와 같은 문제를 겪는 분이 있다면 도움이 되길 바라며...

문제 상황

프로젝트에서 MySQL 데이터베이스를 사용하고 있었고, JDBC URL에 useAffectedRows=true 옵션이 설정돼 있었습니다. 사실 이 옵션은 크게 신경 쓰지 않고 넘어갔던 부분인데, 갑자기 Hibernate가 애플리케이션을 기동하면서 Batch update returned unexpected row count from update [0]: actual row count: 0; expected: 1 쿼리에서 오류를 내뿜는 겁니다.

이전에 잘 돌던 코드가 갑자기 안 돌아가니까 당황스러웠죠. 특별히 변경된 부분도 없었고요. 로그를 뒤지고 설정을 하나씩 뜯어보다가 결국 원인은 이 useAffectedRows=true 옵션에 있다는 걸 알게 되었습니다.

문제의 원인

알고 보니 useAffectedRows=true는 MySQL의 UPDATE 쿼리가 데이터를 업데이트할 때 실제로 바뀐 행만 영향을 받은 행 수로 처리하도록 만드는 옵션이더군요. 좀 더 구체적으로 설명하자면:

  • 기본값인 useAffectedRows=false 상태에선, 데이터가 실제로 바뀌지 않아도 UPDATE 쿼리가 영향을 받은 행 수를 1로 반환합니다. 쉽게 말해 "업데이트 시도했다!" 정도로 처리하는 거죠.
  • 반면 useAffectedRows=true로 설정하면, 데이터가 바뀌지 않으면 영향을 받은 행 수를 0으로 반환합니다. Hibernate는 여기서 혼란을 느끼게 됩니다.

사실, 에러 로그에서도 정직하게 설명이 되있었습니다.

Batch update returned unexpected row count from update [0]: actual row count: 0; expected: 1

Hibernate는 업데이트 성공 여부를 반환된 행 수로 판단하기 때문에, useAffectedRows=true 옵션이 활성화돼서 데이터가 바뀌지 않으면 0이 반환됩니다. Hibernate는 이걸 업데이트 실패로 오해해서 예외를 발생시키고, 결국 애플리케이션이 기동에 실패하는 거죠.

해결

useAffectedRows=false 로 변경 또는 제거.

마치며

mysql 은 다른 DB 와 다르게 JDBC URL 에 옵션이 많이 붙기 때문에 정확히 어떠한 설정인지 알고 쓰는게 좋을 거 같습니다.
에러 로그는 거짓말 하지 않습니다..

profile
공부한 것을 잊지 않기 위해, 고민했던 흔적을 남겨 성장하기 위해 글을 씁니다.

0개의 댓글