ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2021.09.09 기록장
    TIL 2021. 9. 5. 22:39

    ToDo

    • 알고리즘 문제 풀기
    • 책 읽기
    •  

    Done

    •  

    Weekly goal

    • 책 읽기

     

    1. db 풀은 동적으로 어떻게 증가시킬 것인가?

     

    2. 이벤트 큐 사용 시 트랜젝션이 롤백된다면 이벤트 발생이 옳은가?

    TransactionalEventListener(호출 트랜잭션이 커밋되어야 발동)을 통해 강 결합을 피할 수 있다.

    예로 회원가입 시 이메일을 보내야 한다면 단순히 의존성을 주입해서 해결할 수 있다.

    하지만 부가기능이 점점 더 생긴다면 의존성 주입은 더 늘어날 것이다.

    이를 해결하기 위해 ApplicationEventPublisher를 통해 이벤트만 넘겨주면서 해결할 수 있다.

     

    이벤트를 정의하고 ApplicationEventPublisher에 이벤트를 넘기면 

    bean으로 등록한 리스너가 동작할 것이다.

     

    https://stackoverflow.com/questions/54318637/how-to-sendemail-only-if-transaction-is-success-with-spring-tra nsactions

     

    How to SendEmail only if transaction is success with spring-transactions

    I want to create a user in database and send email with AWS SES to user with this case. if user commit transaction in database success => send email if send email AWS SES failed (checked exception...

    stackoverflow.com

    https://cheese10 yun.github.io/event-transaction/

     

    ApplicationEventPublisher 기반으로 강결합 및 트랜잭션 문제 해결 - Yun Blog | 기술 블로그

    ApplicationEventPublisher 기반으로 강결합 및 트랜잭션 문제 해결 - Yun Blog | 기술 블로그

    cheese10yun.github.io

    https://www.baeldung.com/spring-events

     

    3. 2개의 트랜잭션이 동시에 일어난다면?

    result) 병행 제어 기법 중에 하나인 로킹을 통해 데이터 일관성을 보장한다.

    result) 겪었던 문제에서는 음식점에 쓰기 lock(비관적 lock)을 걸어서 다른 곳에서 참조하지 못하게 한 뒤에 뒤의 로직을 처리한다.

     

    동시에 같은 데이터에 접근하여 변경 연산을 수행 시 문제가 될 수 있기에

    병행 제어를 통해 트랜젝션을 수행해야 한다.

     

    병행 제어가 등장하게 된 이유를 살펴보자.

     

    1. 갱신 분실

    둘 다 리드를 같이하고 트랜젝션 2에 의해 덮어써진다.

    트랜젝션 1은 갱신 분실의 문제를 겪는다.

     

    이를 해결하기 위해서 병행 제어를 통해 순차적으로 트랜젝션이 수행하도록 해야 한다.

     

    2. 모순성

    트랜젝션 1과 트랜젝션 2는 비슷한 구조이다. 하나의 트랜젝션 안에서 리드, 라이트를 2번씩 하고 있다.

    근데 트랜잭션 1이 실행되고 있을 때 트랜잭션 2가 중간에 끼어들어 실행이 되게 되면 트랜젝션 2는 처음 읽었을 때의 정보와 나중에 읽었을 때의 정보가 다르게 된다.

    이는 모순성이라고 한다.

    이의 해결법은 동시에 수행되지 않고 순차적으로 실행되게 병행 제어를 해야 한다.

     

    3. 연쇄 복귀

    이것도 중간에 끼어들 때의 문제이다.

    모순성은 중간에 끼어들어 데이터의 모순성이 생길 때이고 이번에는 모순성이 성립되기 전에 장애가 발생한다면

    트랜젝션 1은 롤백이 되어야 한다는 것이다. 근데 트랜젝션 2가 중간에 변경된 데이터를 통해 변경을 했으니 트랜젝션 2도 같이 롤백이 되어야 하지만 이미 완료보고가 되었기에 그렇지 못하다는 것이다.

    이는 아까와 같이 병행 제어를 통해 각각 순차적으로 실행되게 해야 한다.

     

     

    여태 병행 제어를 하지 않으면 발생하는 문제들을 알아봤다.

     

    해결법인 병행 제어는 트랜젝션들의 연산을 실행하는 순서가 중요하다. 

    트랜젝션 스케줄 방법에는 3가지가 존재한다.

    직렬 스케줄, 비 직렬 스케줄, 직렬 가능 스케줄

     

    1. 직렬 스케줄

    인터리빙 방식을 사용하는 것이 아닌 트랜잭션의 연산들을 순차적으로 실행시키는 것이다.

    이는 병행 제어라고 보기 힘들다. 그래서 잘 사용하지 않는 스케줄 방식이다.

     

    2. 비 직렬 스케줄

    중간에 끼어들어 들 수 있는 방식이다. 그렇기에 위에 설명한 3가지 문제점들이 발생할 수 있다.

    병행 제어를 하면 비 직렬 스케줄이라고 하더라도 여러 개의 경우의 수가 나올 수 있다.

    그래서 어떨 때는 데이터가 온전하고, 어떨 때는 그렇지 않을 수 있다.

    위의 사진도 전자는 직렬 스케줄로 돌렸을 때와 결괏값이 같지만 후자는 같지 않다. 그렇기에 후자는 결과를 보장해주지 않는 비 직렬 스케줄인 것이다.

     

    3. 직렬 가능 스케줄

    이는 직렬 스케줄과 같은 결과를 보장해주는 비 직렬 스케줄이다.

    단, 모든 비 직렬 스케줄이 직렬 가능한 것은 아니다.

    다수의 데이터 베이스는 직렬 가능성을 보장하는 병행 제어 기법을 사용한다.

     

     

    병행 제어 기법

    병행 제어 기법은 여러 트랜잭션을 병행 수행하면서도 정확한 결과를 얻을 수 있는 직렬 가능성을 보장받기 위해 사용한다.

    모든 트랜잭션이 따르면 직렬 가능성을 보장받을 수 있는 규약을 정의하고, 트랜잭션들이 따르도록 하는 것이다.

     

    가장 많이 사용하는 기법은 로킹 기법이다.

     

    1. 로킹 기법

    동일한 데이터에 접근하지 못하도록 락과 언락을 반복하는 것이다.

    read나 write를 할 때 lock를 걸고 수행이 완료되면 unlock을 해야 한다.

     

    lock을 규모는 크게는 데이터베이스에서 작게는 속성까지 가능하다.

    전자는 병행 제어라 보기 어렵고 후자는 제어가 쉽지 않다.

     

    로킹 기법에 read와 write를 할 때 모두 lock을 걸면 하나의 트랜젝션만이 권한을 가지게 된다.

    근데 read권한은 동시에 일어나도 문제가 되지 않는다. 그렇기에 wirte만 lock을 걸 수 있다.

     

    이를 2가지로 분류할 수 있다. 공용 lock과 전용 lock이다.

    read는 열어주는 것이 공용 lock이고 다 막는 것이 전용 lock이다.

     

     

    근데 로킹 기법을 모두 지켜도 트랜잭션은 직렬 가능성을 완벽하게 보장하지 못한다.

    read write 할 때 모두 lock을 걸지만 나중에는 데이터 결과가 예상한 값과 다르게 나온다.

    이러한 문제는 트랜젝션 1이 너무 빨리 unlock을 했기 때문이다. 

     

    그래서 lock과 unlock 만들 사용하는 로킹 규약은 완전하지 않다. 

     

    2. 2단계 로킹 규약

    lock과 unlock의 수행 시점에 대한 새로운 규약을 추가한다.

    트랜잭션 스케줄의 모든 트랜잭션이 2단계 로킹 규약을 준수하면 해당 스케줄은 직렬 가능성이 보장된다.

     

    2단계 규약은 특정 시점에만 lock연산을 실행할 수 있고 unlock 또한 특정 시점에만 가능하다는 것이다.

    확장단계(lock만 가능), 축소 단계(unlock만 가능)라고 한다

    isolation 레벨은 uncommit 상태로 예측할 수 있다

    isolation level과 동시성은 trade off관계인 것 같다

     

    10-40과 다른 점은 트랜젝션 1이 첫 번째 unlock을 실행하기 전에 필요한 모든 데이터에 lock연산을 실행한다는 점이다.

     

    병행 제어 기법 중에 하나인 로킹 규약 중 2단계 로킹 규약까지 하면 스케줄의 직렬 가능성을 보장할 수 있다.

    하지만 교착상태가 발생할 수 있다.

     

    동시에 실행은 되지만 데이터를 읽을 때는 락을 걸어버린다.

     

    여태 read를 동시에 하고 write도 따로 할 수 있다는 것이 동시 실행이라고 생각했는데,

    그것보다는 트랜잭션이 순서대로 실행되는 것이 아닌 동시에 실행되지만 특정 데이터에 접근, 수정할 때는 lock을 거는 것이 병행 제어 기법 중에 하나인 로킹 방식인 것이다.

     

    'TIL' 카테고리의 다른 글

    2021.09.11 기록장  (0) 2021.09.11
    2021.09.10 기록장  (0) 2021.09.09
    2021.09.05 기록장  (0) 2021.09.04
    2021.09.03~04 기록장  (0) 2021.09.02
    2021.09.02 기록장  (0) 2021.09.01

    댓글

Designed by Tistory.