문득 트랜잭션 트랜잭션이라 이야기 하는데 그럼 과연 트랜잭션이 의미하는것은 무엇인지 궁금했습니다.
이를 해결하기 위해 트랜잭션을 공부하게 되었습니다. 트랜잭션의 성질과 정의를 공부했습니다.
제가 공부한 내용에 대한 설명은 아래와 같습니다.
특징
- DB에서 병행제어 및 회복 작업시 처리되는 작업의 단위.
- 하나의 트랜잭션은 commit이 되거나 rollback이 된다.
이 두 가지 특징을 생각하면 동시에 들어온 요구사항을 제어할 수 있으며, 오류가 발생 시 이를 회복(복구)을 할 수 있습니다. 그리고 작업을 정상적으로 완료하여 관리자(시스템)에게 알려주는 것이 commit이며, 만약 오류가 발생할 경우 rollback을 통해 작업 전 상태로 복구를 완료 후 관리자에게 알려주는 것임을 알 수 있습니다.
성질(ACID)
- 원자성(Atomicity)
- 일관성(Consistency)
- 독립성(Isolation)
- 지속성(Durability)
트랜잭션 성질들이 의미하는 바는 각각 다르지만 전체적으로 하나의 목표를 향하고 있습니다.
바로 데이터의 확실성과 일관된 유지입니다. 데이터는 변경이 될 경우 원하는 목표 전부 온전히 변경이 이루어져야만 하고, 변경이 완료될 경우 데이터는 정상적인 방법으로 추가적인 변경이 있기 전까지 영구적으로 반영이 되어야 합니다. 만약 데이터 변경 도중 오류가 발생할 경우 기존데이터로 복구하여 데이터의 결함이 없도록 일관되게 유지를 하는 것이 목표입니다.
이런 성질을 가지고 DB와 Spring Framework에서는 어떻게 작동 혹은 사용하는지 알아보았습니다.
- DB(MySQL)
기본적으로 MySQL은 명령어를 실행할 경우 자동으로 Commit을 실행합니다. 그렇기에 트랜잭션의 유무에 따른 상황을 비교를 해보기 위해 트랜잭션을 지원하는 엔진과 미지원 엔진을 이용한 비교로 어떻게 작동하는지 확인하였습니다.
트랜잭션 지원하는 엔진으로 InnoDB를 사용하였고, 미지원 엔진으로는 MyISAM을 사용하였습니다.
아래에 각 엔진 별(트랜잭션 지원 or 미지원 별) Insert할때 PK 참조에러가 발생했을때 처리되는 차이를 보여주는 결과입니다.
트랜잭션 미지원 엔진에서 실험(MyISAM)
7번째 라인 insert에서 PK 참조에러가 발생하였습니다. 이후 실행한 select 결과입니다.
분명 에러가 발생하였지만 Rollback이 안되고 1,2,3이 값으로 들어간 모습을 확인 할 수 있습니다.
Insert를 할때 1,2 까진 데이터가 잘 생성이 되었지만 3이란 값은 이미 존재하는 PK였기에 에러를 출력합니다.
1부터3 까지 넣는것이 하나의 작업이지만 트랜잭션 미지원으로 rollback 개념이 없기에 2까지만 데이터를 입력하고 이후 에러 발생으로 인한 중지로 작업이 끝난 상태입니다.
만약 트랜잭션을 지원하는 엔진으로 실험하면 어떻게 될지 아래 예시로 보여드리겠습니다.
트랜잭션 지원 엔진(InnoDB)
우선 생성과 이미 중복된 값이 있는 에러까지 동일하게 진행하되, 엔진만 변경하였습니다.
그리고 이제 select를 통해 결과를 확인해 보겠습니다.
트랜잭션 실행 중 오류가 발생하여 Rollback이 정상 작동하여 값이 insert 이전으로 돌아간 것을 확인 할 수 있습니다.
MySQL은 8.0 버전부터 InnoDB가 기본으로 적용되어 트랜잭션이 자동으로 설정(auto commit)이 되어있습니다.
물론 모든 명령어에 다 작동하는것은 아니고 DDL(create, drop, alter, rename, truncate)는 rollback의 대상이 아닙니다.
- Spring Framework
Spring에서는 PlatformTransactionManager가 존재합니다. 이를 통해 트랜잭션을 인터페이스로 활용할 수 있습니다.
트랜잭션 매니저를 통해 try-catch안에 commit과 rollback을 구현할 수 있습니다. 다만 트랜잭션 코드들과 비지니스 코드가 결합이 되어 있는 경우가 상당수기에 AOP(Aspect Oriented Programming)라는 개념을 통해 이를 분리 해서 관리합니다. 관점 지향 프로그래밍이란 말 답게 필요한 관점(여기선 트랜잭션 관점)을 중점으로 둔 프로그래밍입니다.
이를 통해 우리가 원하는 트랜잭션을 비지니스 코드와 분리하여 관리 할 수 있습니다.
두개의 선언적 트랜잭션(어노테이션)을 통해 사용할 수 있습니다.
- Aspect
인터페이스 혹은 등록된 Bean에 적용이 가능합니다. 다만 인터페이스를 권장합니다.
- Transactional
트랜잭션을 적용할 인터페이스, 클래스, 메소드 등에 붙여 적용합니다.
'개발잡담 > 공부' 카테고리의 다른 글
멀티쓰레드는 쓰레드랑 어떤게 다를까 (0) | 2023.09.13 |
---|---|
쓰레드(Thread)는 무엇일까? (feat. JAVA) (0) | 2023.09.08 |
힙? 스택? 메모리란 무엇일까 (0) | 2023.09.07 |
Buffer란 무엇일까? (0) | 2023.09.06 |