ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 성장하자! - 트랜잭션
    데이터베이스 2025. 3. 19. 15:44

    이 글을 작성하는 이유는 내가 최근에 기술면접을 보았다.

     

    거기 질문 중에 하나였던 "트랜잭션을 왜 쓸까요?" 였다.

     

    나는 단순하게 "변경사항이 있으면 commit 하거나 예기치 못한 예외가 있으면 Rollback를 해주기 위해서 사용한다" 라고 답을 했다. (너무 수준이 낮은 답변이였다고 생각한다.)

     

     그리고 또 이런 질문이 있었는데 "DB Lock 알고 있나요?", "트랜잭션 격리 수준이 뭘까요?"

     

    답을 제대로 못했다...

     

    면접이 끝나고 면접 복기를 하는데 이 질문의 의도가 무엇이고 어떤 답을 했어야 했을까? 라는 생각이 들었다.

     

    그래서 이번 글에서는 MySQL의 동시성에 영향을 미치는 Lock, 트랜잭션, 트랜잭션의 격리 수준에 대해서 다시 공부를 하고자 이 글을 쓴다.


    우선 트랜잭션이다.

     

    단순히 트랜잭션이 무엇인지가 아니라 "트랜잭션을 왜 쓸까요?" 라는 초점을 두고 공부를 해볼거다.

    무슨 이점이 있고 왜 쓸까? 쓰면 어떤 일이 벌어질까? 쓸때 주의점? 어떤걸 신경써야 하지? 말이다.

     

     

    일단 트랜잭션은 데이터의 정합성을 보장하기 위한 기능이다. 

     

    풀어서 이야기를 하자면 위 그림에서

    트랜잭션은 하나의 논리적인 작업에서 여러 쿼리가 있든 상관없이 논리적인 작업 셋 자체가 100% 적용되거나(Commit) 아무것도 적용되지 않아야(Rollback) 함을 보장해 주는 것이다.

     

    위에 그림에서 Commit 과 Rollback 이 화살표로 설명이 되어 있는데 딱히 뭐라고 표현할지 몰라서 그런거다 화살표 방향이랑 좀 많이 의미가 다르다.

     

    그냥 극단적으로 생각하면 Commit 은 작업 100% 완료!  Rollback은 작업 하다가 뭔가 오류가 났어 다시 그 전 상태로 돌아가(0% 완료)! 이런 의미인 것이다.

     

    위에 그림의 쿼리문이 담긴 박스를 트랜잭션이라고 생각하면 된다.

     

    사전적 의미로는 

    • 단일한 논리적인 작업 단위.
    • 논리적인 이유로 여러 SQL문들을 단일 작업을 묶어서 나눠질 수 없게 만든것.
    • 트랜잭션의 SQL 문들 중에 일부만 성공해서 DB에 반영되는 일은 일어나지 않는다.

    Commit

    • 지금까지 작업한 내용을 DB에 영구적으로 저장하고 트랜잭션을 종료한다.

    Rollback

    • 지금까지 작업들을 모두 취소하고 트랜잭션 이전 상태로 되돌리고 트랜잭션을 종료한다.

     

    사용 패턴으로는

    • 트랜잭션 시작.
    • 데이터를 읽거나 쓰는 등의 SQL 문들을 포함해서 로직을 수행.
    • 일련의 과정들이 문제 없이 동작하면 commit.
    • 중간에 문제가 발생했다면 트랜잭션을 rollback 한다.

    이런식으로 동작을 한다.


    그럼 무슨 이점이 있을까?

     

    작자의 생각은 부분 업데이트 현상이 발생하면 실패한 쿼리로 인해 남은 레코드를 다시 삭제하는 재처리 작업이 필요 할 수 있다는 점이다.

    실행하는 쿼리가 하나라면 뭐 재처리 작업은 간단하겠지만 2개 이상의 쿼리가 실행되면 실패에 대한 재처리 작업은 많이 복잡하고 까다로울 것이다. 

    위 글을 읽었을때 막상 안느껴지죠? 

     

    아래 코드 흐름을 한번 보시죠

    만약 트랜잭션이 지원되지 않고 일반 sql 문 작성하듯이 동작을 하면 부분 업데이트의 결과로 쓰레기 데이터가 남아 있을 가능성이 있다.

     

    하지만 트랜잭션이 지원된다면? (InnoDB)

     

    확실히 차이나죠? 써야겠지?  쓰자! 가 아니라 어차피 요즘 InnoDB 라서 트랜잭션을 지원해준다.

     

    그럼 사용할때 주의사항은 뭐가 있을까?

     

     

    주의사항

     

    코드에서 트랜잭션의 범위를 최소화 해야한다.

     

    일단 커넥션을 생각해보자

    애플리케이션 서버에서 우리는 커넥션 풀에 커넥션을 만들어 놓고 필요할때만 가져다가 쓰고 반납하는 형식이다.

     

    굳이 커넥션이 필요하지 않을때는 안가지고 와야한다. 이 말은 즉 필요한 최소의 코드에서만 사용하라는 뜻이다.

     

    트랜잭션도 다시 말해 범위를 최소화 해야한다.

     

    1) 시작 (커넥션 생성, 트랜잭션 시작)
    
    
    
    2) 사용자의 로그인 여부 확인
    
    
    
    3) 사용자의 글쓰기 생성 데이터 validation
    
    
    
    4)  업로드된 파일 저장 
    
    
    
    5) 입력 내용 DBMS 저장, 첨부 파일 정보를 DBMS에 저장 
    
    
    
    6) 저장된 내용이나 관련된 내용을 조회
    
    
    
    7) 게시물 등록에 대한 알림 메일 발송 
    
    
    
    8) 알림 메일 발송 내용을 DBMS에 저장
    
    
    
    9) 끝 (트랜잭션 종료, 커넥션 반납)

     

    위에 플로우를 보면

     

    실제로 트랜잭션이 필요한 지점은 어디일까? 

     

    5번부터 트랜잭션이 필요하다. 왜냐하면 2번, 3번 은 단순히 조회이기 때문이고

    4번은 별도의 스토리지에 보내기 때문에 트랜잭션이 필요없다.

     

    그리고 트랜잭션은 어디에서 끝내면 좋을까? 

     

    나는 7번 전이라고 생각한다 

    만약 트랜잭션이 실행되고 있는 상황에 메일 전송이나 네트워크를 통해 원격 서버와 통신하는 등과 같은 작업에서 만약 메일 서버와 통신 할 수 없는 상황이 발생한다면 서버와 db서버까지 위험해지는 상황이 발생한다.

     

    데이터베이스 커넥션은 개수가 제한적이어서 각 단위 프로그램이 커넥션을 소유하는 시간이 길어질수록 사용 가능한 여유 커넥션의 개수는 줄어든다.

    그리고 각 단위 프로그램에서 커넥션을 가져가기 위해 기다려야 하는 상황이 발생할 수도 있다.

     

     

    그렇다면 어떤 방식으로 다시 해볼까

     

    1) 시작 
    
    2) 사용자의 로그인 여부 확인
    
    3) 사용자의 글쓰기 생성 데이터 validation
    
    4)  업로드된 파일 저장 
    
    -> 커넥션 생성
    -> 트랜잭션 시작
    5) 입력 내용 DBMS 저장, 첨부 파일 정보를 DBMS에 저장 
    -> 트랜잭션 종료
    
    
    6) 저장된 내용이나 관련된 내용을 조회
    
    7) 게시물 등록에 대한 알림 메일 발송
    
    -> 트랜잭션 시작
    8) 알림 메일 발송 내용을 DBMS에 저장
    -> 트랜잭션 종료
    
    
    9) 끝 (트랜잭션 종료, 커넥션 반납)

     

    간단하게 이렇게 할 것 이다

     

    이럼으로써 커넥션을 가지고 있는 범위와 트랜잭션의 범위를 최소화 할 수 있고 이렇게 해야한다.


    그럼 MySQL에서 트랜잭션을 지원하지 않은 스토리지 엔진은 무엇일까?

    -> MyISAM, MEMORY가 있다.

     

    그럼 지원하는 스토리지 엔진은?

    -> InnoDB이다


    마무리

     

    이제 마무리로 "트랜잭션을 왜 쓸까요?" 라는 질문에 

     

    이제 나는 답은

    한마디로 말을 하자면 데이터 정합성과 무결성을 유지하기 위해 사용을 합니다.

    여러 개의 SQL 문이 하나의 논리적인 작업 단위를 이룰 때 트랜잭션을 사용하지 않으면 데이터가 일관되지 않거나 일부만 적용되는 문제가 발생합니다. 이런 이유 때문에 트랜잭션을 사용합니다. 

    라고 답을 할 것이다.

     

     

     

    그 다음 글은 격리 수준에 대해서 이야기를 할 것이다.

Designed by Tistory.