티스토리 뷰

데이터베이스

[Database] 8. 트랜잭션, 동시성 제어, 회복

망나니개발자 2017. 12. 12. 16:10
반응형

[ 본 사진은 쉽게 배우는 오라클로 배우는 데이터베이스 개론과 실습 ppt에서 캡처했습니다. ]

이번 장에서는 트랜잭션(Transaction), 동시성 제어(Locking or Currency Control), 회복(Recovery)에 대해 알아보겠습니다.


1. 트랜잭션(Transaction)



[ 트랜잭션 ]

  • 트랜잭션: DBMS에서 데이터를 다루는 논리적인 작업의 단위

  • DB에서 데이터를 다룰 때 장애가 일어난 경우 데이터를 복구하는 작업의 단위가 된다.

  • DB에서 여러 작업이 동시에 같은 데이터를 다룰 때가 이 작업을 서로 분리하는 단위가 된다.

  • 트랜잭션은 전체가 수행되거나 또는 전혀 수행되지 않아야 한다.(All or Nothing)

우리가 데이터베이스에 삽입, 수정, 삭제 등의 작업을 할 때, 여러 개의 작업들을 하나의 트랜잭션으로 묶습니다. 즉, 트랜잭션은 DBMS에서 데이터를 다루는 논리적인 작업의 단위가 됩니다. 예를 들어 A계좌(박지성)에서 B계좌(김연아)로 돈을 이체하는 경우에 이 업무는 A에서 돈을 빼고 B에서 돈을 더하는 2가지의 Update문으로 나뉘게 됩니다. 그리고 이것들은 개별적으로 수행되는 것이 아니라 하나의 트랜잭션으로 묶이게 되며 하나의 트랜잭션이 실행될 때 이 2개의 SQL문이 연속적으로 실행됩니다. 그러므로 2개의 UPDATE문이 하나의 트랜잭션으로 묶여있다고 가정할 때 1개의 SQL만 실행되는 상황은 발생하지 않고 이를 All or Nothing 이라 합니다. 이어서 위의 계좌 이체 트랜잭션이 일어나는 세부 과정에 대해서 알아보도록 하겠습니다.


[ 트랜잭션 수행 과정 ]

  1. A계좌의 값을 하드디스크(데이터베이스)에서 주기억장치 버퍼로 읽어온다.

  2. B계좌의 값을 하드디스크(데이터베이스)에서 주기억장치 버퍼로 읽어온다.

  3. A 계좌에서 10000원을 인출한 값을 저장한다.

  4. B 계좌에서 10000원을 입금한 값을 저장한다.

  5. A 계좌의 값을 주기억장치 버퍼에서 하드디스크(데이터베이스)에 기록한다.

  6. B 계좌의 값을 주기억장치 버퍼에서 하드디스크(데이터베이스)에 기록한다.

위와 같은 트랜잭션의 수행 과정은 2가지 방법으로 나뉘어집니다. 먼저 2가지 방법을 알기 전에 커밋(Commit)이라는 개념을 알아야합니다. 여기서 Commit이란 트랜잭션의 수행이 완료됨을 트랜잭션 관리자에게 알려 주는 연산입니다. 2가지 방법은 Commit이 어느 위치에 들어가는지에 따라서 달라지는데, 4번까지 수행한 후 Commit을 할 수 있고, 6번까지 종료한 후 Commit을 할 수 있습니다. 여기서 DBMS는 사용자에게 빠른 응답을 위해 방법1을 택한다고 합니다. 

방법1의 실제 동작: ①-②-③-④-Commit(부분 완료)-⑤-⑥-완료



[ 트랜잭션의 ACID 성질 ]

  • 원자성(Atomicity): 트랜잭션에 포함된 작업은 전부 수행되거나 전부 수행되지 않아야 한다.

  • 일관성(Consistency): 트랜잭션을 수행하기 전이나 후나 데이터베이스는 항상 일관된 상태를 유지해야 한다.

  • 고립성(Isolation): 수행 중인 트랜잭션에 다른 트랜잭션이 끼어들어 변경중인 데이터 값을 훼손하지 않아야한다.

  • 지속성(Durability): 수행을 성공적으로 완료한 트랜잭션은 변경한 데이터를 영구히 저장해야 한다.

데이터베이스는 일반적인 프로그램과 다르게 4가지의 성질을 지니는데, 이를 ACID 성질이라고 합니다. 먼저 원자성이란 앞에서 보았던 All or Nothing의 성질으로 트랜잭션이 원자처럼 더 이상 쪼개지지 않는 하나의 프로그램 단위로 동작해야 한다는 의미합니다. 트랜잭션이 중간에 끊기면 이후에 해당 트랜잭션의 어디서부터 이어 수행되어야 하는지 모르기 때문에 원자성이라는 성질을 지니게 되었습니다. 또한 트랜잭션은 트랜잭션의 수행 전과 후에 일관된 상태를 유지해야 하고 이것을 일관성이라고 합니다. 예를 들어 어떤 테이블의 기본키와 같은 속성은 유지되어야 한다는 것 또는 A에서 B로 돈 이체를 할 때 A와 B계좌의 돈의 총합은 같아야한다는 것 등이 있습니다. 데이터베이스는 클라이언트들이 같은 데이터를 공유하는 것이 목적이므로 여러 트랜잭션이 동시에 수행되어야 합니다. 이때 트랜잭션은 상호 간의 존재를 모르고 독립적으로 수행되어야 한다는 것이 고립성입니다. 고립성을 격리성이라고 얘기하기도 하는데 이를 유지하기 위해서는 여러 트랜잭션이 동시에 접근하는 데이터에 대한 제어가 필요합니다. 마지막으로 트랜잭션은 지속성이라는 성질을 지녀야합니다. 지속성은 트랜잭션의 성공 결과 값은 장애발생 후에도 변함없이 보관되어야 한다는 것으로 트랜잭션이 정상적으로 완료(Commit)된 경우에는 버퍼의 내용을 하드디스크(데이터베이스)에 확실히 기록하여야 하며, 부분 완료(Partial Commit)된 경우에는 작업을 취소(Aborted)하여야 합니다. 즉, 정상적으로 완료 혹은 부분완료된 데이터는 DBMS가 책임지고 데이터베이스에 기록하는 성질이 지속성이며 영속성이라고 표현하기도 합니다.


[ 트랜잭션과 DBMS ]

  • DBMS는 원자성을 유지하기 위해 회복(복구)관리자 프로그램을 작동시킴.

  • DBMS는 일관성을 유지하기 위해 동시성 제어 알고리즘과 무결성 제약조건을 활용함.

  • DBMS는 고립성을 유지하기 위해 동시성 제어 알고리즘을 작동시킴.

  • DBMS는 지속성을 유지하기 위해 회복 관리자 프로그램을 이용함.

어떤 트랜잭션이 실행되다가 장애에 의해 부분 완료되는 상황은 원자성과 지속성이라는 속성에 위배됩니다. 그래서 DBMS는 이를 유지하기 위해 회복 관리자 프로그램을 이용하는데, 일부만 진행된 트랜잭션을 취소시켜 원자성을 유지할 뿐 아니라 값을 트랜잭션 이전의 상태로 복원시켜 지속성을 유지시켜줍니다. 또한 일관성과 고립성을 유지하기 위해서 값에 동시에 접근하지 않도록 하므로 동시성 제어(Locking)를 활용하여 이를 해결합니다. 파일 시스템과 같은 경우처럼 값이 덮어 씌워지는(Overwrite) 경우 일관성이 무너질 수 있고 그러한 경우는 고립성에 위배되는 경우이므로 Locking을 하여 이를 만족시킵니다. 여기에 더해 DBMS는 잘못된 값에 대한 입력이 오면 일관성이 무너질 수 있으므로 이를 유지시키기 위해 무결성 제약조건도 활용합니다.




[ 기타 개념들 ]

  • 롤백(Rollback): 트랜잭션이 행한 모든 연산을 취소시키거나 트랜잭션을 재시작함.

  • DBMS는 일관성을 유지하기 위해 무결성 제약조건을 활용함.

  • DBMS는 고립성을 유지하기 위해 동시성 제어 알고리즘을 작동시킴.

  • DBMS는 지속성을 유지하기 위해 회복 관리자 프로그램을 이용함.

Rollback 연산은 트랜잭션의 실행 중에 장애가 발생한 경우에 수행됩니다. 장애가 발생한 경우는 데이터베이스에 일부만 반영되어 일관되지 못한 상태를 가질 수 있으므로 모두 취소하거나 트랜잭션을 재시작해야 합니다. 트랜잭션은 활동(Active), 부분완료(Partially Committed), 완료(Committed), 실패(Failed), 철회(Aborted)의 5가지 상태를 가지게 됩니다. 여기서 활동은 트랜잭션이 Begin_transaction으로 부터 실행을 시작하였거나 실행 중인 상태를 의미합니다. 부분 완료는 마지막 명령문을 실행시킨 직후의 상태를 의미하며 실패 또는 완료의 상태로 전이하게 됩니다. 실패는 트랜잭션의 실행 중에 장애나 오류가 발생하여 정상적인 실행을 더 이상 할 수 없는 상태이며 Rollback 연산을 수행한 상태인 철회 상태로 전이하게 됩니다. 위에서 Rollback에 의해 트랜잭션이 재시작 되거나 강제종료 되는 경우가 있다고 하였는데, 철회의 원인이 트랜잭션 자체의 논리적인 오류가 아닌 경우에는 재시작되며 트랜잭션 철회의 원인이 트랜잭션 내부의 논리적인 오류에 의해 오류를 수정해야 하는 상황이거나 얻고자 하는 데이터가 데이터베이스에 존재하지 않는 경우에 강제 종료 됩니다.  




2. 동시성 제어(Currency Control)



[ 동시성제어 ]

  • 다중 사용자 환경에서 둘 이상의 트랜잭션이 동시에 수행될 때, 일관성을 해치지 않도록 트랜잭션의 데이터 접근 제어

  • 다중 사용자 환경을 지원하는 DBMS의 경우, 반드시 지원해야 하는 기능

위에서  배운 고립성은 상호 간의 트랜잭션을 독립적으로 만들어 주었습니다. 그런데 2개 이상의 트랜잭션이 하나의 값에 접근하는 경우에는 어떻게 될까요? 2개의 트랜잭션이 모두 읽는 경우에는 문제가 발생하지 않지만, 1개의 트랜잭션은 쓰고 1개의 트랜잭션은 읽는 경우에 상황에 따라 오손 읽기, 반복불가능 읽기, 유령데이터 읽기 문제가 발생할 수 있으며, 2개의 트랜잭션이 모두 쓰기(Write) 시 무제어 병행 수행을 하는 경우에 갱신 손실, 모순성, 연쇄 복귀 등의 문제가 발생할 수 있습니다.



[ 갱신 손실(Lost Update) ]

  • 하나의 트랜잭션이 갱신한 내용을 다른 트랜잭션이 덮어씀으로써 갱신이 무효화가 되는 것을 의미

  • 두 개의 트랜잭션이 한 개의 데이터를 동시에 갱신(Update)할 때 발생

  • 데이터베이스에서 절대 발생하면 안되는 현상

갱신 손실은 1장의 파일 시스템에서 발생했던 문제와 유사합니다. 하나의 값에 계속해서 덮어쓰기(Overwrite)하여 데이터의 갱신이 무효화 되는 현상입니다. 초기값 X = 1000이 있고, 트랜잭션 T1은 X +=300, 트랜잭션 T2는 X-=500 이라 할 때, 동시성 제어를 해주지 않으면 1000이라는 값이 T1에 의해 1300이 된 상태에서 T2가 아직 1300으로 Write 되기 전인 X=1000을 Read하여 1300-500이 아니라 1000-500이 수행되어 500을 갖게 되었고 T1과 T2가 순차적으로 값을 저장하여 덮어씌워지는 값의 손실을 갱신손실이라 합니다. 



[ 모순성(Inconsistency) ]

  • 다른 트랜잭션들이 해당 항목 값을 갱신하는 동안 한 트랜잭션이 두 개의 항목 값 중 어떤 것은 갱신되기 전의 값을 읽고 다른 것은 갱신된 후의 값을 읽게 되어 데이터의 불일치가 발생하는 상황

초기값 X=1500, Y=1000이 있고, 트랜잭션 T1은 X와 Y를 300 증가, 트랜잭션 T2는 X와 Y를 3배씩 증가시킨다고 합시다. 트랜잭션 T1이 수행될 때 X와 Y는 각각 1500과 1000이 읽혀야 합니다. T1이 수행되면서 X만을 1800으로 증가시키고 Write된 다음에 Y를 수행하는 것이 아닌 트랜잭션 T2가 수행된다고 합시다. 그러면 T2에 의해 X와 Y는 각각 5400과 3000이 되고 다시 T1의 Y가 Read를 해야하는 상황에서 1000이 아니라 3000이 읽히게 됩니다. 이렇게 어떤 값은 갱신 전의 값을, 다른 값은 갱신 후의 값을 읽어 데이터가 불일치하는 것을 모순성이라 합니다. 




[ 연쇄 복귀(Cascading Rollback) ]

  • 두 트랜잭션이 동일한 데이터 내용을 접근할 때 발생

  • 한 트랜잭션이 데이터를 갱신한 다음 실패하여 Rollback 연산을 수행하는 과정에서 갱신과 Rollback 연산을 실행하고 있는 사이에 해당 데이터를 읽어서 사용할 때 발생할 수 있는 문제

초기값 X=1500, Y=1000과 X를 300 증가시키고 Y를 200 감소시키는 트랜잭션 T1과 X항목을 3배 증가시키는 트랜잭션 T2가 있다고 합시다. T1이 X를 300 증가시키고 Write 하여 1800이 된 상황에서 T2 트랜잭션이 실행되어 X를 3배하여 Write한 후 종료되었다고 가정합시다. 그리고 T1이 이제 Rollback 연산을 하여 X를 1500으로 다시 돌려놓으려고 하는데 T2는 이미 해당 트랜잭션을 완료하여 종료되었으므로 롤백할 수가 없게 되버리는 문제가 발생합니다. 


[ 트랜잭션 스케줄(Transaction Schedule) ]

  • 직렬 스케줄(Serial Schedule)

  • 비직렬 스케줄(Nonserial Schedule)

  • 직렬 가능 스케줄(Serializable Schedule)

트랜잭션들은 삽입, 수정, 삭제 등과 같은 연산들로 이루어져있는데 여기서 트랜잭션 스케줄이란 그 연산들의 실행 순서를 의미합니다. 직렬 스케줄의 경우에는 트랜잭션의 연산을 모두 순차적으로 실행하는 유형을 의미합니다. 즉, 하나의 트랜잭션이 실행되면 해당 트랜잭션이 완료되어야 다른 트랜잭션이 실행될 수 있습니다. 비직렬 스케줄은 트랜잭션의 직렬 수행 순서와 상관없이 병행 수행하는 스케줄을 의미합니다. 그러므로 한 트랜잭션이 진행중인 상황에서 다른 트랜잭션이 실행될 수 있습니다. 마지막으로는 직렬가능 스케줄이 있는데 직렬 스케즐과 동등한 비직렬 스케줄을 의미합니다. 쉽게 설명하자면 서로 영향을 주지 않는 직렬 스케줄을 비직렬적으로 수행하겠다는 것입니다. 



[ 직렬 가능 스케줄 ]

  • 두 개의 트랜잭션이 Read 연산만을 수행할 것이라면, 상호 간섭이 발생되지 않으며 연산의 순서도 중요하지 않다.

  • 두 개의 트랜잭션이 같은 데이터 항목에 접근하지 않는다면 상호 간섭이 발생되지 않으며 연산의 순서도 중요하지 않다.

  • T1이 X에 Write연산을 하고 T2가 X에 Read 또는 Write 연산을 한다면 실행 순서는 중요하다.

[ 락(Lock) ]

  • 로킹(Locking)기법: 트랜잭션들이 동일한 데이터 항목에 대해 임의적인 병행 접근을 하지 못하도록 제어하는 것

  • 트랜잭션 T가 데이터 항목 X에 대해 Read(X) or Write(X)연산을 수행하려면 반드시 lock(X) 연산을 해주어야 함

  • 트랜잭션 T가 실행한 lock(X)에 대해서는 해당 트랜잭션이 종료되기 전에 반드시 unlock(x)연산을 해주어야 함

  • 트랜잭션 T는 다른 트랜잭션에 의해 이미 lock이 걸려 있는 X에 대해 다시 lock(X)를 수행시키지 못한다.

  • 트랜잭션 T가 X에 lock을 걸지 않았다면, unlock(X)를 수행시키지 못한다.

즉 여러 개의 트랜잭션들이 하나의 데이터로 동시에 접근하려고 할 때 이를 제어해주는 도구가 바로 Lock이다. 락은 트랜잭션이 읽기를 할 때 사용하는 공유락(LS, Shared Lock)읽고 쓰기를 할 때 사용하는 배타락(LX, Exclusive Lock)으로 나뉩니다. 트랜잭션 T가 데이터 항목 X에 대하여 Shared-Lock을 설정할 경우, 트랜잭션 T는 해당 데이터 항목에 대해서 읽을 수 있지만 기록할 수 없습니다. 그리고 Read는 서로 영향을 주지 않으므로 다른 트랜잭션도 Shared-Lock이 설정된 X에 대해서 Shared-Lock을 동시에 설정할 수 있습니다. 트랜잭션 T가 데이터 항목 X에 대하여 Exclusive-Lock을 설정할 경우, 트랜잭션 T는 해당 데이터 항목에 대해서 읽을 수도 있고, 기록할 수도 있습니다. Write는 영향을 주는 작업이므로 다른 트랜잭션은 Exclusive-Lock을 설정한 데이터 항목 X에 대해서 어떠한 lock도 설정할 수 없습니다.


[ 공유락과 베타락을 사용하는 규칙 ]

  • 데이터에 락이 걸려있지 않으면 트랜잭션은 데이터에 락을 걸 수 있다.

  • 트랜잭션이 데이터 X를 읽기만 할 경우 LS(X)를 요청하고, 읽거나 쓸 경우 LX(X)를 요청한다.

  • 다른 트랜잭션이 데이터에 LS(X)를 걸어둔 경우, LS(X)의요청은 허용하고 LX(X)는 허용하지 않는다.

  • 다른 트랜잭션이 데이터에 LX(X)를 걸어둔 경우, LS(X)와 LX(X) 모두 허용하지 않는다.

  • 트랜잭션이 락을 허용받지 못하면 대기 상태가 된다.

[ 2단계 락킹 ]

  • 로킹 단위: 로킹 기법에서 사용하는 lock 연산의 대상

  • 2단계 로킹 규약: 락을 걸고 해제하는 시점에 제한을 두지 않으면 두 개의 트랜잭션이 동시에 실행될 때 데이터의 일관성이 깨질 수 있어서 로킹 단계를 2개로 구분하여 이를 방지하는 방법

  • 확장 단계(Growing Phase): 트랜잭션은 새로운 lock 연산만 할 수 있고, unlock 연산은 할 수 없는 단계

  • 축소 단계(Shrinking Phase): 트랜잭션은 unlock 연산만 실행할 수 있고, lock 연산은 실행할 수 없는 단계

로킹단위가 속성->튜플->릴레이션->데이터베이스로 커질수록 구현이 용이하고 록의 수가 적어지며 제어가 간단하지만 병행성이 떨어지는 반면 로킹단위가 작을수록 구현이 복잡하고 로크의 수가 많고 제어 기법이 복잡하여도 병행성을 높일 수 있습니다. 2단계 로킹 규약(2PLP: Two-Phase Locking Protocol)은 트랜잭션들이 lock하는 시간과 unlock을 하는 시간을 구분하여 수행하도록 하는 것입니다. 2단계 로킹 규약을 사용하지 않으면 아래의 그림과 같이 일관성이 위배되는 문제가 발생할 수 있습니다. 그래서 임의의 시간에 lock 또는 unlock을 하는 것이 아니라 확장 단계와 축소 단계를 두어 이를 해결해줍니다. 2PLP는 직렬 가능성을 보장할 수 있는 규약으로 가장 많이 사용되지만 교착상태가 발생할 가능성이 있지만 교착상태(데드락, Deadlock)에 빠질 수 있으므로 이를 해결해주어야 합니다.



[ 데드락(Deadlock) ]

  • 데드락(Deadlock): 두 개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락을 획득하고 상대방 데이터에 대하여 락을 요청하면 무한 대기 상태에 빠질 수 있는 현상

  • 데드락은 교착상태라고도 한다.

데이터베이스의 데드락과 운영체제의 데드락은 상당히 비슷합니다. 위의 정의를 풀어 설명하면 공통된 자원을 이용하기 위해 여러 개의 트랜잭션이 서로 lock을 걸어주다가 무한 대기 상태에 빠지는 것을 데드락이라 합니다. 예를 들어 먼저 T1에서 A에 대해 락을 걸고 T2에서 B에 대해 락을 걸었다고 합시다. 그리고 나서 T1에서 B에 대해 락을 걸고 T2가 A에 대해 락을 건다면 T1과 T2는 서로 A, B에 대한 락을 유지하며 무한루프에 빠지게 됩니다. 일반적으로 데드락이 발생하면 DBMS가 T1 혹은 T2 중 하나를 강제로 중지시켜 한 트랜잭션은 정상적으로 실행되며 중지된 트랜잭션에서 변경한 데이터는 원래 상태로 되돌려 놓습니다.



3. 트랜잭션 고립 수준



[ 오손읽기(Dirty Read) ]

  • 읽기 작업을 하는 트랜잭션 1이 쓰기 작업을 하는 트랜잭션2가 작업한 중간 데이터를 읽기 때문에 발생하는 문제

  • 작업중인 트랜잭션 2가 작업을 Rollback한 경우 트랜잭션 1은 무효가 된 데이터를 읽게 되고 잘못된 결과를 도출한다.

아래의 그림과 같이 T1이 T2가 Rollback되기 전의 데이터를 읽었고, T2가 Rollback이 되면 T1이 의미가 없는 값을 갖게 되므로 문제가 발생합니다. 그리고 이러한 무효가 된 데이터를 읽게되어 발생하는 문제를 오손읽기(Dirty Read)라고 합니다.



[ 반복불가능 읽기(Non-repeatable Read) ]

  • 트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(Update) 르랜잭션 1이 다시 한번 데이터를 읽을 때 생기는 문제

  • 트랜잭션 1이 읽기 작업을 다시 한 번 반복할 경우 이전의 결과와 다른 결과가 나오는 현상

아래의 그림과 같이 T1이 먼저 값을 읽었고 T2가 값을 갱신(Update)하였다고 합시다. 그리고 T1이 다시 값을 읽으려고 하면 바로 전에 읽은 값이 달라지는데 이를 반복불가능 읽기라고 합니다. 




[ 유령데이터 읽기(Phantom Read) ]

  • 트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(Insert) 트랜잭션 1이 다시 한번 데이터를 읽을 때 생기는 문제

  • 트랜잭션 1이 읽기 작업을 다시 한 번 반복할 경우 이전에 없던 데이터(유령 데이터)가 나타나는 현상

아래의 그림과 같이 T1이 먼저 값을 읽었고, T2가 값을 삽입(Insert)하였다고 합시다. 그리고 T1이 다시 값을 읽으려고 하면 바로 전에는 없었던 값이 읽히게 되는데 이를 유령데이터 읽기라고 합니다.




[ 트랜잭션 고립 수준 명령어(Transaction Isolation Level Instruction) ]

  • DBMS는 트랜잭션을 동시에 실행시키면서 락보다 좀 더 완화된 방법으로 문제를 해결하기 위해 제공하는 명령어

트랜잭션이 작업을 수행하다 보면 위의 오손 읽기, 반복불가능 읽기, 유령데이터 읽기와 같은 문제를 직면할 수 있습니다. 그래서 Lock보다는 완화된 방법으로 트랜잭션을 동시에 실행시키면서, 발생하는 문제를 해결하기 위해 DBMS가 제공하는 명령어가 바로 트랜잭션 고립 수준 명령어(Transaction Isolation Level Instruction)입니다. 여기에는 고립 수준을 나타내는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE과 같은 명령어들이 있습니다.



[ READ UNCOMMITTED ]

  • 고립 수준이 Level 0으로 가장 낮은 명령어로, 자신의 데이터에 아무런 공유락을 걸지 않는다.

READ UNCOMMITTED는 자신의 데이터에 아무런 공유락도 걸지 않지만 배타락은 데이터의 갱신손실 문제 때문에 걸어주어야 합니다. 또한 다른 트랜잭션에 공유락과 배타락이 걸린 데이터를 대기하지 않고 읽습니다. SELECT 문을 수행하는 경우 해당 데이터에 Shared Lock이 걸리지 않는 Level입니다. 따라서, 어떤 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 B라는 아직 완료되지 않은 데이터(오손 데이터) B를 읽을 수 있습니다.



[ READ COMMITTED ]

  • 고립 수준이 Level 1인 명령어로, 오손 페이지의 참조를 피하기 위해 자신의 데이터를 읽는 동안 공유락을 걸지만 트랜잭션이 끝나기 전에라도 해지 가능하다.

다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행됩니다. SQL Server가 Default로 사용하는 Isolation Level으로 SELECT 문이 수행되는 동안에 Shared Lock이 걸리게됩니다. 그러므로 어떤 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안에 다른 사용자는 해당 데이터에 접근할 수 없습니다. 



[ REPEATABLE READ ]

  • 고립 수준이 Level 2인 명령어로, 자신의 데이터에 설정된 공유락과 배타락을 트랜잭션이 종료될 때까지 유지하여 다른 트랜잭션이 다신의 데이터를 갱신(Update)할 수 없도록 한다.

다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행됩니다. 다른 고립화 수준에 비해 데이터의 동시성(Concurrency)이 낮아 특별하지 않은 상황이라면 사용하지 않는 것이 좋습니다. 즉, 트랜잭션이 완료될 때까지 SELECT문이 사용하는 모든 데이터에 Shared Lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정이 불가능합니다. 예를 들어 SELECT number FROM A WHERE number BETWEEN 1 and 10을 수행하였고, 이 범위에 해당하는 number가 2 or 3이 있는 경우 다른 사용자가 number가 2 or 3인 행에 대한 UPDATE가 불가능하지만 나머지 범위에 대해서 행을 INSERT하는 것이 가능합니다. 



[ SERIALIZABLE ]

  • 고립 수준이 Level 3으로 가장 높은 명령어로, 실행 중인 트랜잭션은 다른 트랜잭션으로부터 완벽하게 분리된다.

데이터 집합에 범위를 지어 잠금을 설정할 수 있기 때문에 다른 사용자가 데이터를 변경(UPDATE) 또는 삽입(Insert)하려고 할 때 트랜잭션을 완벽하게 분리할 수 있습니다. 이 명령어는 가장 제한이 심하고 동시성도 낮습니다. 즉, SELECT 문이 사용하는 모든 데이터에 Shared Lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정(UPDATE) 및 입력(INSERT)가 불가능합니다. 앞의 Repeatable Read의 경우에는 1에서 10사이의 number에 대한 삽입이 가능하였지만 SERIALIZABLE은 SELECT의 대상이 되는 모든 테이블에 Shared Lock을 설정하는 것과 같아서 나머지 범위에 대한 INSERT가 불가능합니다. 




4. 회복(Recovery)



[ 장애의 유형 ]

  • 트랜잭션 장애: 트랜잭션의 실행 시 논리적인 오류로 발생할 수 있는 에러 상황

  • 시스템 장애: H/W 시스템 자체에서 발생할 수 있는 에러 상황

  • 미디어 장애: 디스크 자체의 손상으로 발생할 수 있는 에러 상황

트랜잭션 실행 시 발생할 수 있는 에러 상황의 원인으로는 트랜잭션 내에 잘못된 데이터 입력, 데이터의 부재, 오버플로우(Overflow), 자원의 한계 초과 요청, 어떤 수를 0으로 나누게 되는 연산 등이 있습니다. 시스템 장애는 하드웨어 자체에서 발생할 수 있는 에러로 하드웨어의 잘못된 작동으로 메인 메모리에 저장되어 있는 정보가 손실되거나 교착 상태의 발생으로 더 이상 트랜잭션 작업이 수행될 수 없는 상황에서 발생합니다. 마지막으로 미디어 장애는 디스크의 손상으로 발생할 수 있는 에러로 디스크 헤드 손상이나 고장으로 인해 저장장치 내의 정보가 일부 또는 전부 손상될 수 있는 상태입니다.




[ 회복(Recovery) ]

  • 데이터베이스를 장애가 발생했던 이전의 상태로 복구시켜서 일관된 데이터베이스 상태를 만드는 것

데이터베이스를 갱신하는 과정에서 장애가 발생한 경우 회복절차를 수행하여 장애 발생 이전의 데이터베이스로 만드는 것을 회복이라고 합니다. 회복을 위한 데이터 복사본을 만드는 방법에는 덤프(Dump)를 이용하는 방법과 로그(Log)를 이용하는 방법 2가지가 있습니다. 덤프는 가장 기본적인 기법으로 일정 주기로 원본의 데이터베이스의 모든 내용을 다른 저장장치에 복사하는 것입니다. 로그는 변경 이전의 데이터베이스를 기준으로 변경 연산이 발생할 때 마다 로그 파일을 작성하여 기록하고, 회복할 때 로그에 적힌 내용을 사용하여 복원하는 방법입니다.



[ 로그파일(Log File) ]

  • 트랜잭션이 반영한 모든 데이터의 변경사항을 데이터베이스에 기록하기 전에 미리 기록해두는 별도의 데이터베이스

  • 안전한 하드디스크에 저장되며 전원과 관계없이 기록이 존재

  • 로그의 구조: <트랜잭션 번호, 로그의 타입, 데이터 항목 이름, 수정 전 값, 수정 후 값>

  • 로그의 타입: START, INSERT, UPDATE, DELETE, ABORT, COMMIT 등 트랜잭션의 연산 타입

로그(Log)란 트랜잭션이 데이터의 변경사항을 데이터베이스에 직접 기록하기 전에 미리 기록해두는 별도의 데이터베이스로 특정한 구조를 가지고 기록이 되며 장애 발생 시 복원을 위해서 사용됩니다. 실제로 아래와 같은 형식으로 로그가 기록됩니다. 또한 트랜잭션이 기록되는 정보들은 아래의 그림에서 참고할 수 있습니다.

<T1, START>

<T1, UPDATE, Customer(박지성).balance, 10000, 9000>

<T1, UPDATE, Customer(김연아).balance, 10000, 11000>

<T1, COMMIT>


[ 로그 파일을 이용한 회복 ]

  • 데이터의 변경이 발생할 때 마다 생성되는 로그 파일을 이용하는 것

  • 데이터의 변경 기록을 저장해 둔 로그 파일을 이용하면 시스템 장애도 복구 가능

DBMS는 트랜잭션이 종료되었는지 혹은 중단되었는지 여부를 판단하여 종료된 경우에는 종료를 확정하기 위하여 REDO(재실행)을 하고 중단된 경우에는 없던 일로 되돌리기 위해 UNDO(취소)를 진행합니다. REDO는 장애가 발생한 후 시스템을 다시 가동을 했을 때, 로그 파일에 트랜잭션의 시작(START)이 있고 종료(COMMIT)이 있는 경우 로그를 보면서 트랜잭션이 변경한 내용을 다시 기록하는 과정입니다. UNDO는 장애가 발생한 후 시스템을 재가동했을때, 로그 파일에 트랜잭션의 시작(START)만 있고 종료(COMMIT)이 없는 경우 완료하지 못했지만 버퍼의 변경 내용이 데이터베이스에 기록되어 있을 가능성이 있기 때문에 로그를 보면서 트랜잭션이 변경한 내용을 원상복구시키는 과정입니다. REDO의 경우에는 T1에 의해 변경된 모든 데이터 항목들을 로그 파일에 있는 새로운 값(New Value)으로 대체시켜야 하고 이를 T1의 첫 번째 로그 레코드 부터 진행합니다. 하지만 UNDO의 경우에는 T1에 의해 변경된 모든 데이터 항목들을 로그 파일에 있는 예전 값(Old Value)로 대체하여야 하고 장애가 발생한 마지막 로그 레코드부터 거꾸로 진행합니다.




트랜잭션이 시작하면 변경연산에 대해서 계속 로그 파일에만 기록을 하고 실제 데이터베이스에는 반영을 하지 않습니다. 그러다가 부분 완료까지 성공을 하면 로그 파일을 참조하여 실제 데이터베이스의 값을 변경시킵니다. 트랜잭션이 실패한 경우에는 연산이 로그파일에만 저장이 되어있고 데이터베이스에는 반영되어있지 않으므로 추가 작업이 필요 없지만 중간에 부분 완료를 거친 후에 트랜잭션 실패가 발생한다면, 데이터베이스에 일부 기록된 내용이 있을 수 있으므로 이러한 경우에는 UNDO를 해주어야 합니다. 아래의 그림에서 왼쪽은 트랜잭션이 성공한 경우이며 오른쪽은 트랜잭션이 실패한 경우에 해당합니다.



[ 로그 파일의 회복 방법 ]

  • 즉시 갱신(Immediate Update): 갱신 데이터->로그, 버퍼->데이터베이스 작업이 부분완료 전에 동시에 진행될 수 있으며, 부분 완료가 되면 갱신 데이터는 로그에 기록이 끝난 상태

  • 지연 갱신(Deferred Update): 갱신 데이터->로그가 끝난 후 부분 완료를 하고 버퍼->데이터베이스 작업이 진행되는 방법

즉시 갱신은 갱신된 데이터를 로그에 기록하는 작업과 버퍼의 데이터를 데이터베이스에 옮기는 작업이 동시에 진행될 수 있으며 부분완료가 된 경우는 로그에 기록이 끝난 상태인 반면에 지연 갱신은 갱신된 데이터를 로그에 작성하는 작업이 끝난 후에야 버퍼의 데이터를 데이터베이스로 옮기는 작업이 진행될 수 있습니다.


[ 체크포인트(CheckPoint, 검사점) ]

  • 로그는 그대로 기록을 유지하면서, 회복 관리자가 정하는 일정한 시간 간격으로 검사 시점을 생성하는 것

  • 회복 시 많은  양의 로그를 검색하고 갱신하는 시간을 줄이기 위함

  • 체크포인트가 있으면 로그를 이용한 회복 기법은 좀 더 간단해짐

DBMS에서 회복을 할 때 처음부터 마지막 로그 기록까지 한번에 처리하려면 시간적으로 오래 걸릴 수 밖에 없습니다. 그러므로 특정 시간 마다 검사를 하여 문제가 없음을 확인하면 다음번 에러 발생 시 회복을 시작하는 시점을 앞으로 당길 수 있습니다. 그래서 체크 포인트 시점에는 다음과 같은 작업을 수행하게 됩니다. 먼저 주기억장치의 로그 레코드를 모두 하드디스크의 로그 파일에 저장합니다. 그리고 트랜잭션 수행 중에 변경된 버퍼 내의 내용을 하드디스크의 데이터베이스에 저장합니다. 그리고 나서 체크포인트를 로그 파일에 다음과 같이 표시합니다. <Checkpoint T_List>: T_list는 현재 수행 중인 트랜잭션의 리스트입니다.


  • 체크포인트 이전에 [Commit] 기록이 있는 경우: 아무 작업이 필요 없다.

  • 체크포인트 이후에 [Commit] 기록이 있는 경우: REDO(T)를 진행한다.

  • 체크포인트 이후에 [Commit] 기록이 없는 경우: 즉시 갱신 방법 사용시 UNDO(T) 진행

체크포인트 이전에 Commit이 있는 경우는 로그에 체크포인트가 나타나는 시점은 이미 변경 내용이 데이터베이스에 모두 기록된 후이기 때문에 아무런 작업도 필요하지 않습니다. 체크포인트 이후에 Commit 기록이 있는 경우는 체크포인트 이후에 변경 내용이 데이터베이스에 반영되지 않았으므로 REDO를 진행합니다. 체크포인트 이후에 Commit 기록이 없고 즉시 갱신 방법을 사용한 경우는 갱신 데이터를 로그에 작성하는 과정과 버퍼의 내용을 데이터베이스에 기록하는 작업이 동시에 이루어지므로 버퍼의 내용이 데이터베이스에 반영됐을 수도 있기 때문에 원상복구 시켜야하므로 UNDO를 해야합니다. 하지만 체크포인트 이후에 Commit 기록이 없고 지연 갱신 방법을 사용한 경우는 갱신 데이터를 로그에 작성한 후 Commit을 시작해야 버퍼의 내용을 데이터베이스에 기록하는 작업이 이루어지므로 아무 작업도 해줄 필요가 없습니다. 





m/24 











관련 포스팅

  1. 데이트베이스 시스템 (1/8)

  2. 관계데이터 모델 (2/8)

  3. SQL 기초 (3/8)

  4. SQL 고급 (4/8)

  5. 데이터베이스 프로그래밍 (5/8)

  6. 데이터 모델링(Data Modeling) (6/8)

  7. 정규화(Normalization) (7/8)

  8. 트랜잭션, 동시성 제어, 회복 (8/8)



반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함