Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7기][이건창] 스프링에서 트랜잭션 처리 #958

Merged
merged 11 commits into from
Mar 14, 2022

Conversation

this-is-spear
Copy link
Member

안녕하세요 ☺️
이번 PR은 트랜잭션의 간단한 내용과 스프링에서 트랜잭션 처리를 전체적으로 정리했습니다.

편하게 보기

@this-is-spear this-is-spear changed the title 스프링에서 트랜잭션 처리 [7기][이건창] 스프링에서 트랜잭션 처리 Mar 10, 2022
`Unchecked Exception`과 `Error` 예외가 발생했을 때 롤백 처리가 되고, `**Exception` 예외와 예외가 발생하지 않은 경우에는 커밋한다.** 동작 방식을 변경을 원한다면 설정을 통해 동작 방식을 변경할 수 있다.

<aside>
🚧 체크 예외를 커밋 대상으로 삼은 이유는 체크 예외가 예외적인 상황에서 사용되기 보단 반환값을 대신해 비즈니스적인 의미로 담은 결과로 많이 사용되기 때문이라고 한다.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 문장을 보고 얼마전에 봤던 논란의 백선장님 영상이 떠오르네요 ....
https://www.youtube.com/watch?v=_WkMhytqoCc&ab_channel=%EB%B0%B1%EA%B8%B0%EC%84%A0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗...!! 이 글도 얼마전 백기선님 유튜브 보다가 탄생하게 된 글입니다...!! 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

체크 예외가 예외적인 상황에서 사용되기 보단 반환값을 대신해 비즈니스적인 의미로 담은 결과로 많이 사용되기 때문이라고 한다.
이 부분이 사실 잘 이해가 안되는 부분이긴 하네요 ㅋㅋ

공식문서에는 EJB 컨테이너의 기본옵션이 runtime exception일때 트랜잭션을 롤백하는 것이고 Spring은 EJB의 컨벤션을 따른걸로 보이네요.

Although EJB container default behavior automatically rolls back the transaction on a system exception (usually a runtime exception), EJB CMT does not roll back the transaction automatically on an application exception (that is, a checked exception other than java.rmi.RemoteException
). While the Spring default behavior for declarative transaction management follows EJB convention (roll back is automatic only on unchecked exceptions), it is often useful to customize this behavior.

참고: https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#transaction-declarative

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checked Exception 같은 경우에는 별도로 예외 처리를 해야하는 예상 가능한 예외이기 때문이라는 의미였는데 설명이 너무 부족했습니다. 수정하도록 하겠습니다...!! 😭
Spring은 EJB의 컨벤션을 따라가는 건 처음알았습니다..!! 유익한 정보 감사합니다. ☺️

- 이미 시작된 트랜잭션이 있으면 참여하고 없으면 새로 시작한다.
- 격리수준(`isolation`) :
- `DEFAULT`
- 사용하는 데이터 엑세스 기술 또는 데이터베이스 드라이버의 기본 값 설정을 따른다.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 옵션은 스프링 애플리케이션에서 연결된 RDBMS 에 따라 다르게 적용이 되는 것 일까요???
(이 부분을 잘 몰라서 ....)

여기서 궁금 ....

  1. MySQL 과 그 외 RDBMS
  • MySQL 은 디폴트가 Repeatable read 이고 PostgreSQL 은 Read commit
  • 그렇다면 스프링은 어떤 것을 사용하든 RDBMS 의 디폴트 값에 맞춰서 설정을 해주는 것일까요 ??
  1. 다중 DataSource 를 사용할 때
  • MySQL 과 PostgreSQL 을 모두 사용하는 애플리케이션이 있다고 할 때
  • 스프링은 routing 되는 DB 에 맞춰서 다르게 적용을 하는 것일까요 ???

매번 궁금했던 내용이였는데 ... 이 주제에서 이야기를 꺼내면 좋을 것 같아 .... 코멘트(질문??)을 드립니다. ㅠㅠ

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 재미있는 질문이네요. 저도 궁금합니다 :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEFAULT 옵션을 적용하면 사용하는 데이터 액세스 기술 또는 DB 드라이버의 디폴트 설정을 따릅니다. 만약 JDBC를 이용해 데이터베이스에 접근한다면, 첫 번째로 드라이버인 JDBC 드라이버나 DataSource 등에 설정한 격리 수준을 따릅니다.

SET TRANSACTION ISOLATION LEVEL(Transact-SQL) - SQL Server

JDBC 드라이버를 통해 기본 격리 수준을 설정할 경우, 격리 수준 옵션은 한 설정 파일에 한 번만 설정할 수 있으며 명시적으로 변경할 때까지는 해당 연결에 대한 설정이 그대로 유지된다고 합니다. 그리고 JDBC 드라이버의 경우는 READ_COMMITTED가 기본값으로 설정이 됩니다.
(해당 설정이 스프링에서ISOLATION_DEFAULT이 됩니다.)
Why mysql JDBC driver returns TRANSACTION_READ_COMMITTED as default isolation level

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 스프링은 트랜잭션에서 설정할 수 있는 격리 수준 내이면 RDBMS의 기본 격리 수준을 설정해줄 수 있다고 생각을 합니다. ☺️
  2. 스프링은 추상화를 지원하기 때문에 공통적인 메서드를 호출하면 해당 데이터베이스에 맞는 드라이버가 실행이 되고, 드라이버에 맞는 기본 격리 수준으로 설정이 됩니다.
  3. 다중 DataSource를 사용해 트랜잭션을 설정한다면 각각의 DataSource에 맞는 기본 격리수준을 따라간다고 생각이 듭니다.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정말 좋은 코멘트 감사합니다. 많은 생각과 고민이 드는 질문이어서 많은 자료를 찾아봤던 것 같아요 ☺️ 찾아본 자료와 내용을 정리하지 못하고 작성하는 것이다보니 주관적인 생각이 많이 들어가 신뢰도가 떨어지는 점 정말 죄송합니다. 😭
틀린 부분이 있다면 수정하겠습니다. 감사합니다. 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

덕분에 궁금했었던 부분을 다시 정리할 수 있었습니다. !!

isolation level 은 사용하고 있는 RDBMS 에 따라 다르게 적용이 되는 것 같더라고요

image

근데 참고해주신 글을 보고 찾아보니 MySQL connector 같은 경우 READ_COMMITTED 를 디폴트로 사용하고 있는 것 같습니다.
(원래는 Repeatable_Read)

image

그리고 사내에서는 Maria DB 를 사용하여 똑같이 찾아보니 Repeatable_Read 로 확인됩니다.

image

정리하자면 MySQL 은 REPEATABLE_READ 로 동작할 것으로 예상하지만 READ_COMMITTED 로 동작하고
Maria DB 는 예상대로 REPEATABLE_READ 로 동작한다 ?? 인 것 같습니다.

좀 당황스럽네요 ....
이건 좀 더 서치해보고 검증해봐야겠네요 ....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정정합니다. 쌉질했군요 ....

스프링 코드 디버깅 해보니 WAS 띄울 때, 연결된 DB 정보 가져와서 값을 초기화하는 과정이 있네요 !!
(base_project 는 테스트 용으로 생성한 스키마입니다 ...)

image

그리고 @transactional 로 선언이 되어있는 메서드 내에서 아래 코드로 current isolation level 를 조회해보면
디폴트 옵션으로 적용된 경우 REPEATABLE_READ 가 나옵니다.

dataSource.getConnection().getTransactionIsolation()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DB 정보 가져와서 값을 초기화하는 과정이 존재하는 군요!! 심지어 MySQL은 제가 생각한 READ_COMMITTED이 아니라 REPEATABLE_READ일 줄 몰랐습니다..!! 바로 글 수정하겠습니다. 유익한 정보 정말 감사합니다 👍👍👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

관련 내용 정리가 되면 좋을 것 같아서 블로그에 포스팅해보았어요 !! (틀린 내용이 있을 수도 ....)
https://wave1994.tistory.com/188

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 글 감사합니다!! 👍👍

- 트랜잭션 롤백
- 작업을 취소하고 이전 상태로 돌린다.

만약 문제가 생길경우 롤백하도록 설정한다고 가정할 때, 하나의 작업이 문제가 생기지 않고 마무리가 된다면 트랜잭션 커밋을 처리를 해주고, 문제가 생긴다면, 작업 취소를 위해 트랜잭션 롤백 처리를 해줘야 어떻게 처리가 됐는지 여부를 알 수 있다.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
만약 문제가 생길경우 롤백하도록 설정한다고 가정할 때, 하나의 작업이 문제가 생기지 않고 마무리가 된다면 트랜잭션 커밋을 처리를 해주고, 문제가 생긴다면, 작업 취소를 위해 트랜잭션 롤백 처리를 해줘야 어떻게 처리가 됐는지 여부를 알 수 있다.
만약 문제가 생길경우 롤백하도록 설정한다고 가정할 때, 하나의 작업이 문제가 생기지 않고 마무리가 된다면 트랜잭션 커밋을 처리를 해주고, 문제가 생긴다면, 작업 취소를 위해 트랜잭션 롤백 처리를 해줘야 어떻게 처리가 됐는지 여부를 알 수 있다.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타 수정 감사합니다. ☺️

- 트랜잭션 동기화
- 트랜잭션을 시작하기 위한 Connection 객체를 특별한 저장소에 보관해두고 필요할 때 꺼내서 사용할 수 있도록 하는 기술
- 트랜잭션 추상화
- 애플리케이션 각 기술마다 종속적인 코드를 이용하지 않고 일관되게 트랜잭션을 처리할 수 있다.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 말하는 애플리케이션이 DB를 의미하는건가요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

애플리케이션을 설계하면서 각 데이터베이스 기술에 따른 종속적인 코드를 이용하지 않고 일관되게 트랜잭션을 처리할 수 있다. 라는 말을 하고 싶었던 것 같아요!! 바로 수정해야겠습니다. 👍


### 예외 상황에서 롤백(`rollbackFor` or `noRollbackFor`)

`Unchecked Exception`과 `Error` 예외가 발생했을 때 롤백 처리가 되고, `**Exception` 예외와 예외가 발생하지 않은 경우에는 커밋한다.** 동작 방식을 변경을 원한다면 설정을 통해 동작 방식을 변경할 수 있다.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Exception이 예외라는 의미를 담고 있기 떄문에, 중복해서 쓸 필요가 없을거 같아요.
  2. Exception` 예외와 예외가 발생하지 않은 경우에는 커밋한다. 이 문장에서 어떤 Excpetion을 의미하는 것인가요? 어떤 Exception이길래 커밋하는지 궁금해서요 :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 표현하고 싶었던 Exception은 RuntimeException을 제외한 Exception 하위 계층, 즉 checked Excetpion이었습니다. 좋은 지적해주셔서 감사합니다. ☺️

Copy link
Contributor

@ksy90101 ksy90101 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

글 너무 재미있게 봤습니다 :)
추가적으로 아래 글도 한번 읽어보시면 좋을거 같아요 :)
https://d2.naver.com/helloworld/407507
발표 기대하겠습니다!

tis/2022-03-10/스프링에서-트랜잭션-처리.md Outdated Show resolved Hide resolved
`Unchecked Exception`과 `Error` 예외가 발생했을 때 롤백 처리가 되고, `**Exception` 예외와 예외가 발생하지 않은 경우에는 커밋한다.** 동작 방식을 변경을 원한다면 설정을 통해 동작 방식을 변경할 수 있다.

<aside>
🚧 체크 예외를 커밋 대상으로 삼은 이유는 체크 예외가 예외적인 상황에서 사용되기 보단 반환값을 대신해 비즈니스적인 의미로 담은 결과로 많이 사용되기 때문이라고 한다.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

체크 예외가 예외적인 상황에서 사용되기 보단 반환값을 대신해 비즈니스적인 의미로 담은 결과로 많이 사용되기 때문이라고 한다.
이 부분이 사실 잘 이해가 안되는 부분이긴 하네요 ㅋㅋ

공식문서에는 EJB 컨테이너의 기본옵션이 runtime exception일때 트랜잭션을 롤백하는 것이고 Spring은 EJB의 컨벤션을 따른걸로 보이네요.

Although EJB container default behavior automatically rolls back the transaction on a system exception (usually a runtime exception), EJB CMT does not roll back the transaction automatically on an application exception (that is, a checked exception other than java.rmi.RemoteException
). While the Spring default behavior for declarative transaction management follows EJB convention (roll back is automatic only on unchecked exceptions), it is often useful to customize this behavior.

참고: https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#transaction-declarative

| `SERIALIZABLE` | 트랜잭션이 동시에 같은 테이블의 정보를 액세스할 수 없음 | 격리 수준이 가장 높음 |

> 스프링이 제공하는 ISOLATION_DEFAULT 옵션을 적용하게 되면 `PlatformTransactionManager`가 실행이되고 해당 기술에 맞는 격리 수준이 실행이 된다.
> (JDBC를 이용하면 JDBC의 드라이버에 설정된 격리 수준을 먼저 따라간다 해도 무방합니다. 기본 값인 Read commit을 따라가기 때문에 MySQL 데이터베이스를 JDBC 드라이버에 연결하면 JDBC 드라이버의 기본 값인 `READ_COMMITTED`을 따라가게 된다.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DB의 기본설정을 따르는 걸로 알고 있었는데.. 잘못알고 있었네요
👍

@github-actions github-actions bot merged commit 76fcd8a into Meet-Coder-Study:master Mar 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4주차 4주차 글 7기
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants