Spring Transaction, Commit, Rollback

강서진·2024년 1월 5일
0

Spring

목록 보기
9/18
post-custom-banner

2번째 필수강의 ch3. 17강 요약 (Transaction, Commit, Rollback)

트랜잭션 Transaction
더 이상 나눌 수 없는 작업의 단위

  • 원자성 (Atomicity)
    나눌 수 없는 하나의 작업으로 다뤄져야 한다.
  • 일관성 (Consistency)
    수행 전과 후가 일관된 상태를 유지해야 한다.
  • 고립성 (Isolation)
    각 트랜잭션은 독립적으로 수행되어야 한다.
  • 영속성 (Durability)
    성공한 트랜잭션의 결과는 유지되어야 한다.
  • 고립성은 트랜잭션이 서로의 결과에 영향을 주면 안된다는 취지이지만, 상황에 따라 영향이 가야 할 때도 있다. 이를 아이솔레이션 레벨이라고 한다. 레벨이 너무 높으면 한 번에 한 작업만 진행할 수 있어 DB 사용이 불편해진다. 따라서 작업에 따라 적절한 아이솔레이션 레벨을 선택해 처리하는 것이 효율적이다.
  • 커밋 Commit
    작업 내용을 DB에 영구적으로 저장하는 것
  • 롤백 Rollback
    최근 변경사항을 취소하는 것(=마지막 커밋으로 복귀)
  • 자동커밋 Auto Commit
    명령 실행 후 자동으로 커밋이 수행되는 것(롤백 불가)
  • 수동커밋 Manual Commit
    명령 실행 후 명시적으로 commit 또는 rollback을 입력하여 실행하는 것

아이솔레이션 레벨

  • READ UNCOMMITTED (dirty read)
    커밋되지 않은 데이터도 읽기 가능
  • READ COMMITTED (phantom read)
    커밋된 데이터만 읽기 가능
  • REPEATABLE READ <DEFAULT>
    하나의 트랜잭션이 시작된 이후의 다른 트랜잭션으로 인한 변경을 무시
  • SERIALIZABLE (직렬화)
    한 번에 하나의 트랜잭션만 독립적으로 수행

+병렬로 DB에 작업을 하다보면 데이터의 품질이 떨어질 가능성이 있다.


트랜잭션을 테스트해본다. autocommit을 false로 두고, bbbb라는 user를 등록한다. 그리고 bbbb1라는 id만 달라진 user를 추가로 저장한다. 두 과정 중 한 과정에서라도 오류가 발생하면 rollback이 일어나 트랜잭션이 취소된다.
finally 내부에는 Connection을 닫아주는 내용이 들어가야 한다.

두번째로 저장하는 user의 id를 동일한 bbbb로 주었을 경우, Duplicate 에러가 발생해 롤백된다.
두 가지 경우 모두 테스트를 통과하는 것을 확인할 수 있었다.

    @Test
    public void testTransaction() throws Exception {
        Connection conn = null;

        try {
            deleteAll();
            conn = ds.getConnection();
            conn.setAutoCommit(false);

//        String sql = "insert into user_info values ('asdf', '1111', 'kim', 'aaa@aaa.com', '2022-12-02', 'twitter', now())";
            String sql = "insert into user_info values (?,?,?,?,?,?,now())";
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setString(1, "bbbb");
            preparedStatement.setString(2, "1234");
            preparedStatement.setString(3,"abc");
            preparedStatement.setString(4, "aaa@bbb.com");
            preparedStatement.setDate(5, new java.sql.Date(new Date().getTime()));
            preparedStatement.setString(6,"instagram");

            int rowCount = preparedStatement.executeUpdate();

            preparedStatement.setString(1,"bbbb1");
            rowCount = preparedStatement.executeUpdate();

            conn.commit();

        } catch (Exception e) {
            conn.rollback();
            e.printStackTrace();
        } finally {}
    }
post-custom-banner

0개의 댓글