ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MySQL] InnoDB 언두(Undo) 로그와 MVCC란 무엇일까?
    Book/Real MySQL 2021. 7. 29. 16:17
    728x90
    반응형

    언두 영역이란?

    언두 영역은 UPDATE 문장이나 DELETE 문장으로 데이터를 변경했을 때 변경되기 전의 데이터(이전 데이터)를 보관하는 곳입니다.

    UPDATE membere SET name='홍길동' WHERE member_id = '1';

    위 문장의 실행되면 트랜잭션을 커밋하지 않아도 실제 데이터 파일 내용은 홍길동으로 변경됩니다. 그리고 변경되기 전의 값이 Gyunny 였다면, 언두 영역에는 Gyunny라는 값이 백업되는 것입니다. 이 상태에서 사용자가 커밋하게 되면 현재 상태가 그대로 유지되고, 롤백하게 되면 언두 영역의 백업된 데이터를 다시 데이터 파일로 복구합니다.

     

    언두의 데이터는 크게 두 가지 용도로 사용됩니다.

    • 트랜잭션의 롤백 대비용
    • 트랜잭션의 격리 수준을 유지하면서 높은 동시성을 제공



    인서트 버퍼란?

    RDBMS에서 레코드가 INSERT 되거나 UPDATE 될 때는 데이터 파일을 변경하는 작업 뿐 아니라 해당 테이블에 포함된 인덱스를 업데이트하는 작업도 필요합니다. 그런데 인덱스를 업데이트하는 작업은 랜덤하게 디스크를 읽는 작업이 필요하므로 테이블에 인덱스가 많다면 이 작업은 상당히 많은 자원을 소모하게 됩니다. 그래서 InnoDB는 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면 바로 업데이트를 수행하지만, 그렇지 않고 디스크로부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 임시 공간에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상시키게 되는데, 이 때 사용하는 임시 메모리 공간을 인서트 버퍼(Insert Buffer) 라고 합니다.



    리두(Redo) 로그 및 로그 버퍼

    쿼리 문장으로 데이터를 변경하고 커밋하면 DBMS는 데이터의 ACID를 보장하기 위해 즉시 변경된 데이터의 내용을 데이터 파일로 기록해야 합니다. 하지만 이러한 데이터 파일의 변경 작업은 순차적으로 많은 데이터를 한꺼번에 변경하는 것이 아니고 랜덤하게 디스크에 기록해야 하기 때문에 디스크를 상당히 바쁘게 만드는 작업입니다. 그래서 이러한 부하를 줄이기 위해서 대부분의 DBMS에는 변경된 데이터를 버퍼링해 두기 위해 InnoDB 버퍼 풀과 같은 장치가 포함되어 있습니다. 하지만 이 장치만으로 ACID를 보장할 수 없는데 이를 위해 변경된 내용을 순차적으로 디스크에 기록하는 로그 파일을 가지고 있습니다. 더 정확한 명칭은 리두 로그입니다.



    MVCC(Multi Version Concurrency Control)

    일반적으로 레코드 레벨의 트랜잭션을 지원하는 DBMS가 제공하는 기능이며, MVCC의 가장 큰 목적은 잠금을 사용하지 않는 일관된 읽기를 제공하는 데 있습니다.InnoDB는 언두 로그를 이용해 이 기능을 구현합니다.

    INSERT INTO member (m_id, m_name, m_area) VALUES (12, '홍길동', '서울');

    위의 INSERT 문장이 실행되면, 아래의 그림처럼 바뀔 것입니다.

     

    스크린샷 2021-07-29 오후 3 52 56

     

    즉, InnoDB 버퍼 풀에도 생기고, 디스크 영역에도 추가된 것을 볼 수 있습니다.

     

    UPDATE member SET m_area = '경기' WHERE m_id=12;

    스크린샷 2021-07-29 오후 3 54 09

    UPDATE 문장이 실행되면 커밋 실행 여부와 관계 없이, InnoDB의 버퍼 풀은 새로운 값인 경기로 업데이트 됩니다. 아직 COMMIT, ROLLBACK이 되지 않은 상태에서 아래와 같이 레코드를 조회하면 어떤 데이터를 조회해서 올까요?

    SELECT * FROM member WHERE m_id = 12;

    질문에 대한 답은 격리 수준(Isolation Level)에 따라 다릅니다.

    • 만약 격리 수준이 READ_UNCOMMITTED인 경우에는 InnoDB 버퍼 풀이나 데이터 파일로부터 변경되지 않은 데이터를 읽어서 반환합니다. 즉, 데이터가 커밋됐든 아니든 변경된 상태의 데이터를 반환합니다.
    • 그렇지 않고 READ COMMITTED, REPEATABLE_READ, SERIALIZABLE인 경우에는 아직 커밋되지 않았기 때문에 InnoDB 버퍼 풀이나 데이터 파일에 있는 내용 대신 변경되기 이전의 내용을 보관하고 있는 언두 영역의 데이터를 반환합니다.

     

    이러한 위와 같은 과정을 DBMS에서는 MVCC라고 표현합니다. 즉, 하나의 레코드에 대해 2개의 버전이 유지되고, 필요에 따라 어느 데이터가 보여지는지 여러 가지 상황에 따라 달라지는 구조입니다. 지금까지 UPDATE 쿼리가 실행되면 InnoDB 버퍼 풀은 즉시 새로운 데이터로 변경되며 기존의 데이터는 언두(Undo)로 복사되는 과정에 대해서 알아보았습니다. 이 상태에서 COMMIT 명령을 실행하면 InnoDB는 더 이상의 변경 작업 없이 지금의 상태를 영구적인 상태로 만들어버립니다. 하지만 만약 롤백을 실행하면 InnoDB는 언두 영역에 있는 백업된 데이터를 InnoDB 버퍼 풀로 다시 복구하고, 언두 영역의 내용을 삭제해버립니다. 커밋이 된다고 언두 영역의 백업 데이터가 항상 바로 삭제되는 것은 아니다. 이 언두 영역을 필요로 하는 트랜잭션이 더는 없을 때 비로 삭제됩니다.



    Reference

    반응형

    댓글

Designed by Tistory.