SELECT ... FOR UPDATE는 업데이트 전에 결과 Row에 Lock을 설정하기 위한 쿼리이다.
업데이트하고 명시적으로 Commit을 해야만 Lock이 해제된다.
결과 Row를 확인하고 업데이트가 필요없다고 판단되더라도
명시적인 Commit이 필요한 셈이다.
DefaultSqlSession.commit()의 코드는 다음과 같다.
public void commit() {
commit(false);
}
여기에서 사용되는 commit(boolean force)의 코드는 다음과 같다.
public void commit(boolean force) {
try {
executor.commit(isCommitOrRollbackRequired(force));
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
여기에서 사용되는 isCommitOrRollbackRequired(boolean force)의 코드는 다음과 같다.
private boolean isCommitOrRollbackRequired(boolean force) {
return (!autoCommit && dirty) || force;
}
selectXxx()는 dirty 설정을 하지 않기 때문에 Commit은 되지 않는다.
그렇다면 어떻게 해야 할까?
이미 눈치챘겠지만, 다음과 같이 force 파라미터를 true로 설정해서 호출하면 된다.
commit(true);
혹시나 commit() 메소드 호출 후에도 Lock이 해제되지 않는다고 삽질하지 마시길.
Reference:
http://docs.oracle.com/cd/E17952_01/refman-5.1-en/innodb-locking-reads.html



