-
JPA(3) - Transation(트랜잭션)Back-end/JPA 2021. 8. 18. 14:00반응형
안녕하세요. 오랜만에 JPA에 관한 글을 써보려고합니다.
이번 포스팅은 JPA를 사용하면서 @Transactional이라는 어노테이션을 사용하게 됩니다.
저는 이것이 무척 궁금하였고 우아한 테크코스 유투브를 보면서 많은 공부를 하게 되었습니다.
지금부터 트랜잭션이 왜 사용되고 어떻게 작동하며 Spring에서는 어떻게 사용하는지 알려드리겠습니다.
위의 그림은 간단한 계층도입니다. 일반 사용자 같은 경우에는 웹 화면에서 데이터를 조회하면 서버로 요청이 가게되고
서버는 다시 DBMS(Database Management System)으로 요청을 보내게 됩니다.
이 요청을 받은 DBMS는 SQL문을 해석하고 LOG로 기록하여 DB에 정보를 CRUD하게 됩니다.
이러한 하나의 과정을 트랜잭션이라고 생각하시면 됩니다.
트랜잭션은 DB의 완전한 신뢰성을 얻기 위해서 탄생하였습니다.
대부분 Query를 DBMS로 보내 요청을 수행합니다. 그러나 Query가 잘 인식되었는지는 아무도 모릅니다.
나중에 원하는 데이터가 아닌 다른 데이터가 올 수 있고 4개의 데이터를 요청했는데 3개의 데이터만 올 수 있습니다.
이러한 문제를 없애기위해서 트랜잭션이라는 개념을 도입하였습니다.
트랜잭션의 특징
그럼 트랜잭션이 가져야 할 특성에 대해서 살펴보겠습니다.
1. 원자성
모든 일련의 과정을 하나로 해야합니다.
하나라도 실패 시 "Rollback"(되돌리기), 모두 성공 시"Commit"(DB에 반영). All or Nothing특성으로 설명됩니다.
2. 일관성
Trigger를 통하여 모든 내용이 일괄적용이 되도록합니다.(어느 누가 조회해도 같아야함.)
3. 지속성
DB에는 실패 시 어떠한 영향도 받지 않아야합니다. Log로 Rollback실행.
4. 독립성
각 트랜잭션은 독립적으로 수행해야합니다.
이러한 4가지 특성을 가져야 트랜잭션의 개념이 성립됩니다.
그럼 트랜잭션에 앞서서 DBMS가 어떻게 동작하는지 살펴보겠습니다.
DBMS의 동작
위의 그림은 DBMS의 구조를 간략하게 나타낸 그림입니다.
SQL문을 처리하는 질의 처리기, 페이지(DB의 입.출력 단위)를 관리하는 페이지 버퍼,
메모리 및 하드 디스크에 DATA를 저장하는 저장 시스템으로 이루어져 있습니다.
페이지 버퍼는 가장 중요한 역할을 합니다. 이것으로 REDO와 UNDO작업이 이루어지기 때문입니다.
그럼 REDO와 UNDO는 무엇일까요?
UNDO(이전 상태 기록)
UNDO복구는 트랜잭션이 정상 종료가 되지 않았을 경우 수정된 페이지들 다시 되돌리는정책입니다.
여기서 "수정된 페이지를 디스크에 쓰는 기점"을 기준으로 두 가지 정책으로 나뉩니다.
STEAL: 수정된 페이지를 언제든지 디스크에 쓸 수 있는 정책
¬STEAL: 수정된 페이지들을 최소한 트랜잭션 종료 시점(EOT)까지는 버퍼에 유지하는 정책
대부분 STEAL정책을 사용합니다. STEAL정책은 언제든지 수정한 페이지가 디스크에 써질 수도 있는 위험이 있기때문에
필수적으로 UNDO로깅과 복구를 수반해야합니다.
REDO(이후 상태 기록)
REDO복구는 이미 커밋한 트랜잭션의 수정을 재반영하는 복구작업을 말합니다.
이것도 "트랜잭션이 수정한 페이지들을 디스크에도 쓸 것인가"를 여부로 정책이 구분됩니다.
FORCE: 수정했던 모든 페이지를 트랜잭션 커밋 시점에 디스크에 반영하는 정책
¬FORCE: 수정했던 페이지를 트랜잭션 커밋 시점에 디스크에 반영하지 않는 정책
대부분 DBMS는 ¬FORCE정책을 사용합니다. ¬FORCE정책은 수정한 내용이 디스크에 안 써질 수 있기 때문에
필수적으로 REDO로깅과 복구를 수반해야합니다.
따라서 DBMS는 REDO와 UNDO는 필수적으로 필요하게 됩니다.
트랜잭션의 관리
REDO와 UNDO로 트랜잭션을 관리해주는 방법으로는 Log가 대표적으로 사용됩니다.
Log란 모든 데이터베이스 갱신 작업을 기록해놓습니다. 이러한 로깅 방법에 대해서 알아보겠습니다.
로깅 방법이 다양하지만 저희는 물리적인 상태 로깅에 대해서 알아보겠습니다.
물리적인 상태 로깅
물리적 로깅은 갱신 이전, 이후 이미지를 가지고 있어 UNDO는 이전 이미지로 REDO는 이후 이미지로 대체하게 됩니다.
그렇다면 이러한 로그는 어떻게 기록을 할까요? 바로 로그 버퍼를 통하여 기록됩니다.
각 DBMS마다 로그 버퍼는 다르게 구현되어있습니다. 그러나 공통점은 로그 파일의 입출력을 담당하고 있습니다.
이렇게 로그 버퍼를 사용해 write함수와 부수적인 함수를 적용하여 파일에 로깅을 하게 됩니다.
그러나 부수적인 함수가 쓰이면서 느리게 기록 될 수 있습니다.
이것을 개선하는 작업들이 있는데 너무 깊은 내용이라 이해하지 못했습니다.
위와 같이 로그 파일에 로깅을 하고 문제가 발생했을 경우에는 어떻게 작동할까요?
크게 두 가지 경우가 있습니다.
하나는 트랜잭션 철회(사용자 요청,오류발생)복구, 물리적인 시스템에러에 의한 복구가 있습니다.
트랜잭션 철회같은 경우는 UNDO복구가 필요한 로그를 찾아서 그것을 역순으로 UNDO작업을 수햅합니다.
그렇게 하고 보상 로그 레코드(역순 작업했던 것)를 얻어 한번 더 REDO작업을 시행해줍니다.
다음으로 물리적인 시스템에러는 로그 분석 -> REDO ->UNDO과정으로 크게 이루어집니다.
로그 분석은 어디서부터 어디까지 복구해야하는지를 찾아내는 단계입니다.
로그 분석이 끝나면 REDO작업을 실행합니다. 실패한 트랜잭션까지도 REDO합니다.
왜냐하면 이러한 REDO복구가 끝난 DB상태는 장애발생 시점과 같게됩니다.
이러한 상태에서 UNDO명령을 수행하게 됩니다.
이렇게 REDO와 UNDO를 통해서 DBMS는 동작한다는 것을 알았습니다.
그러면 Spring에서는 어떻게 이것이 사용되고 있을까요?
적다보니 내용이 길어져서 나눠서 포스팅하도록 하겠습니다. 긴 글 읽어주셔서 감사합니다.
반응형'Back-end > JPA' 카테고리의 다른 글
JPA(2) - 영속성 컨테이너란? (0) 2021.08.01 JPA(1) - JPA란? (0) 2021.07.31