From dda117da40818a61ea1ed2fcffa2b9c3c28d4049 Mon Sep 17 00:00:00 2001 From: lsj8367 Date: Sat, 12 Nov 2022 10:23:07 +0900 Subject: [PATCH] =?UTF-8?q?:memo:=204.3=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=EA=B3=BC=20=EB=AC=B4=EA=B2=B0=EC=84=B1=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4_\353\254\264\352\262\260\354\204\261.md" | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 "4\354\236\245_\353\215\260\354\235\264\355\204\260\353\262\240\354\235\264\354\212\244/\355\212\270\353\236\234\354\236\255\354\205\230\352\263\274_\353\254\264\352\262\260\354\204\261.md" diff --git "a/4\354\236\245_\353\215\260\354\235\264\355\204\260\353\262\240\354\235\264\354\212\244/\355\212\270\353\236\234\354\236\255\354\205\230\352\263\274_\353\254\264\352\262\260\354\204\261.md" "b/4\354\236\245_\353\215\260\354\235\264\355\204\260\353\262\240\354\235\264\354\212\244/\355\212\270\353\236\234\354\236\255\354\205\230\352\263\274_\353\254\264\352\262\260\354\204\261.md" new file mode 100644 index 0000000..66d24f6 --- /dev/null +++ "b/4\354\236\245_\353\215\260\354\235\264\355\204\260\353\262\240\354\235\264\354\212\244/\355\212\270\353\236\234\354\236\255\354\205\230\352\263\274_\353\254\264\352\262\260\354\204\261.md" @@ -0,0 +1,143 @@ +# 4장. 데이터베이스 + +Created: 2022년 11월 7일 오후 11:57 +Last Edited Time: 2022년 11월 11일 오전 12:08 + +# 4장 데이터베이스 + +## 4.3 트랜잭션과 무결성 + +트랜잭션은 DB에서 하나의 논리적 기능을 수행하기 위한 작업의 단위를 말하며 + +DB에 접근하는 방법은 쿼리이므로, 여러 쿼리를 하나로 묶는 단위를 말한다. + +### 트랜잭션의 특성 + +> 원자성 + +트랜잭션과 관련된 일이 모두 수행되었거나 되지 않았거나를 보장하는 특징 + +All or Nothing 의 개념으로 작업 단위의 일부분만 실행하지 않는다는 것 + +트랜잭션 단위로 여러 로직을 묶을 때 외부 API를 호출하는 것이 있으면 안된다. + +있다면, 롤백을 해야할 경우에 어떻게 해야할 것인지에 대한 해결 방법이 있어야하고 + +트랜잭션 전파를 신경써서 관리해야 한다. + +### 커밋, 롤백 + +커밋은 여러 쿼리가 성공적으로 처리되었다고 확정하는 명령어 + +트랜잭션 단위로 수행되며 변경된 내용이 모두 영구적으로 저장되는 것을 말한다. + +반영을 하는 도중에 에러가 나거나 다른 이슈때문에 이전으로 돌려야 한다면? 할때 사용하는 것이 바로 롤백이다. + +한 트랜잭션 과정을 일어나기 전으로 돌리는 역할을 수행한다. + +이 두가지 기능덕에 데이터의 무결성이 보장되고, 변경 전에 변경사항을 쉽게 확인이 가능하며 해당 작업을 그룹화할 수 있다. + +### 트랜잭션 전파 (Transaction Propagation) + +트랜잭션을 수행할 때는 커넥션 단위로 수행하기 때문에 커넥션 객체를 넘겨 수행한다. + +그렇지만 매번 넘겨주기는 힘들기 때문에 여러 트랜잭션 관련 메소드의 호출을 하나의 트랜잭션에 묶이도록 하는것이 바로 트랜잭션 전파이다. + +스프링에서는 대표적으로 Service Layer에서 `@Transactional` 을 통해 해당 역할을 수행한다. + +스프링의 트랜잭션 전파 전략은 [스프링 Docs](https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html#tx-propagation) 에서 확인이 가능하다. + +```java +@Service +@Transactional +public record DemoService(UserRepository userRepository) { + + @Transactional(readOnly=true) + public User findOne(final Long userId) { + return userRepository.findById(userId).orElseThrow(); + } +} +``` + +### 일관성 + +허용된 방식으로만 데이터를 변경해야 하는 것을 의미함. + +DB에 기록된 모든 데이터는 여러가지 조건, 규칙에 따라 유효함을 가져야 한다. + +### 격리성 + +트랜잭션 수행 시 서로 끼어들지 못함. + +> 트랜잭션 격리수준 + +| 격리수준 | 특징 | 나타나는 현상 | +|---------------------------------------------|--------------------------------------------------------------------------|---------| +| READ_UNCOMMITTED | 트랜잭션이 실행 중일때, 다른 트랜잭션에 의해 수정이 되었지만 커밋이 되지 않았는데도 그 데이터를 읽을 수 있는 경우가 존재한다. | 더티리드 | +| READ_COMMITTED | 가장 많이 사용되는 격리수준 | | +| READ_UNCOMMITTED와는 다르게 커밋하지 않은 정보는 읽을 수 없음. | not-repeatable read | | +| REPEATABLE_READ | MySQL 8.0 의 기본 격리 수준 | 팬텀리드 | +| SERIALIZABLE | 여러 트랜잭션이 동시에 같은 행에 접근할 수 없음. | | + +나타나는 현상자체를 전부 통제함. +교착상태(Deadlock)이 가장 일어날 확률이 높다. | X | + +> Dirty Read + +반복가능하지 않은 조회(Non-Repeatable Read)와 유사하며, 한 트랜잭션이 실행중일 때 다른 트랜잭션에 의해 수정되었지만 아직 **커밋되지 않은** 행의 데이터를 읽을 수 있는 경우 발생함. + +![더티리드](https://user-images.githubusercontent.com/74235102/201449871-7729436b-8ef5-4203-b4a2-32c8e04aade1.png) + +해결방법 + +![더티리드 해결](https://user-images.githubusercontent.com/74235102/201449874-10b030da-167a-4e08-8830-23604dde0a5b.png) + +A의 작업이 아직 커밋되지 않았으니 mysql은 언두영역에 기존의 값을 저장해두고 있는다. + +그래서 B가 select를 조회해도 이전 데이터인 Lara를 반환하게 되어 해결하게 된다. + +> Non-Repeatable Read + +한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데 그 값이 다른경우를 말한다. +![반복읽기](https://user-images.githubusercontent.com/74235102/201449864-205dda3d-655b-4cdb-8df7-f1fa6ff70682.png) + +B의 트랜잭션을 시작해두고 A가 update를 하고 commit을 한 후 + +다시 B가 select 로 조회를 하면 결과가 나오는 현상을 말함. + +OracleDB의 기본 트랜잭션 격리 수준이다. + +해결방법 + +![반복된 읽기 해결](https://user-images.githubusercontent.com/74235102/201449869-88330110-5f49-4384-a2d8-6ed903f94a03.png) + +A의 트랜잭션 번호는 12, B의 트랜잭션 번호는 10이다. + +12번의 트랜잭션이 중간에 update하고 commit을 진행했지만, + +repeatable-read 수준에서는 각 트랜잭션마다 고유의 번호를 가지고있는데 + +자신의 트랜잭션 번호보다 작은 트랜잭션 번호에서 변경한것만 감지가 가능하고, + +그 외에는 못보게되어 같은 쿼리를 2번 수행해도 같은 결과를 볼 수 있게된다. + +> Phantom Read + +![팬텀리드](https://user-images.githubusercontent.com/74235102/201449862-a006e4be-d9e0-4cbc-bd5d-718ff3b9724e.png) + +해결 방안 - mysql의 innodb는 스냅샷을 이용한 일관된 읽기를 사용한다. + +consistent read를 지원하기 때문인데 위에서 봤던 undo log를 이용하여 이 기능을 구현한다. + +insert와 연결되지 않은 select의 경우 다른 트랜잭션의 변경 작업과 관계없이 항상 잠금을 대기하지 않고 바로 실행된다. + +### 4.3.2 무결성 + +데이터의 정확성, 일관성, 유효성을 유지하는 것을 말하고, 무결성이 유지되어야 DB에 저장된 데이터 값과 그 값에 해당하는 현실 세계의 실제 값이 일치하는지에 대한 **신뢰** 가 생긴다. + +| 이름 | 설명 | +|----------|---------------------------------------------------------| +| 개체 무결성 | 기본키로 선택된 필드는 빈 값을 허용하지 않는다. | +| 참조 무결성 | 서로 참조관계에 있는 두 테이블의 데이터는 항상 일관된 값을 유지해야 한다. | +| 고유 무결성 | 특정 속성에 대해 고유한 값을 가지도록 조건이 주어진 경우 그 속성 값은 모두 고유한 값을 가진다. | +| NULL 무결성 | 특정 속성 값에 NULL이 올 수 없다는 조건이 주어진 경우 그 속성 값은 null이 될 수 없다. | \ No newline at end of file