"트랜잭션"의 두 판 사이의 차이
잔글 |
|||
(사용자 9명의 중간 판 52개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
− | '''트랜잭션'''(transaction)이란 "쪼갤 수 없는 업무 처리의 최소 단위"를 말한다. '트렌젝션'이 아니라 '트랜잭션'이 올바른 표기법이다. | + | '''트랜잭션'''(transaction)이란 "쪼갤 수 없는 업무 처리의 최소 단위"를 말한다. '''거래내역'''이라고도 한다. '트렌젝션'이 아니라 '트랜잭션'이 올바른 표기법이다. 영어로 간략히 '''Tx'''라고 표기하기도 한다. 1초당 처리할 수 있는 트랜잭션의 개수를 [[TPS]]라고 한다. |
− | == | + | == 개요 == |
+ | 트랜잭션은 은행 [[ATM]]이나 [[데이터베이스]] 등의 시스템에서 사용되는 더 이상 쪼갤 수 없는 업무 처리의 최소 단위이다. 예를 들어, A라는 사람이 B라는 사람에게 1,000원을 지급하고 B가 그 돈을 받은 경우, 이 거래 기록은 더 이상 작게 쪼갤 수가 없는 하나의 트랜잭션을 구성한다. 만약 A는 돈을 지불했으나 B는 돈을 받지 못했다면 그 거래는 성립되지 않는다. 이처럼 A가 돈을 지불하는 행위와 B가 돈을 받는 행위는 별개로 분리될 수 없으며 하나의 거래내역으로 처리되어야 하는 단일 거래이다. 이런 거래의 최소 단위를 트랜잭션이라고 한다. 트랜잭션 처리가 정상적으로 완료된 경우 [[커밋]](commit)을 하고, 오류가 발생할 경우 원래 상태대로 [[롤백]](rollback)을 한다. | ||
− | 트랜잭션은 | + | == 목적 == |
+ | 트랜잭션은 데이터베이스 서버에 여러 개의 클라이언트가 동시에 액세스 하거나 응용프로그램이 갱신을 처리하는 과정에서 중단될 수 있는 경우 등 데이터 부정합을 방지하고자 할 때 사용한다.<ref name="트랜잭션 성질2"/> 데이터베이스 기능 중, 트랜잭션을 조작하는 기능은 데이터베이스 완전성(integrity) 유지를 확신하게 한다. 단일 트랜잭션은 데이터베이스 내에 읽거나 쓰는 여러 개 쿼리를 요구한다. 이때 중요한 것은 데이터베이스가 수행된 일부 쿼리가 남지 않는 것이다. 예를 들어, 송금을 할 때 한 계좌에서 인출되면 다른 계좌에서 입금이 확인되는 것이 중요하다. 또한 트랜잭션은 서로 간섭하지 않아야 한다. 만약 쿼리 하나가 실패하면, 데이터베이스 시스템은 전체 트랜잭션 또는 실패한 쿼리를 롤백 한다. 이것은 DBMS가 어떻게 사용되고 셋업 되었느냐에 따라 다르다. 트랜잭션은 커밋전에 언제든지 수동으로 롤백 될 수 있다. 간단한 트랜잭션의 경우 아래 양식의 SQL 언어로 데이터베이스 내에서 실행된다.<ref>데이터베이스 트랜잭션 위키백과 - https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98</ref> | ||
+ | * Begin the transaction<ref>〈[https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/begin-transaction-transact-sql?view=sql-server-ver15 BEGIN TRANSACTION(Transact-SQL)]〉, 《마이크로소프트》, 2016-06-10</ref> | ||
+ | --Applies to SQL Server and Azure SQL Database | ||
+ | |||
+ | BEGIN { TRAN | TRANSACTION } | ||
+ | [ { transaction_name | @tran_name_variable } | ||
+ | [ WITH MARK [ 'description' ] ] | ||
+ | ] | ||
+ | [ ; ] | ||
+ | |||
+ | --Applies to Azure SQL Data Warehouse and Parallel Data Warehouse | ||
+ | |||
+ | BEGIN { TRAN | TRANSACTION } | ||
+ | [ ; ] | ||
+ | * Execute several queries(DB내 갱신이 아직 적용되지 않는다.) | ||
+ | * Commit the transaction(트랜잭션이 성공적이며, 갱신이 실제 적용됨.)<ref>〈[https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/commit-transaction-transact-sql?view=sql-server-ver15 COMMIT TRANSACTION(Transact-SQL)]〉, 2016-09-09</ref> | ||
+ | -- Applies to SQL Server (starting with 2008) and Azure SQL Database | ||
+ | |||
+ | COMMIT [ { TRAN | TRANSACTION } [ transaction_name | @tran_name_variable ] ] [ WITH ( DELAYED_DURABILITY = { OFF | ON } ) ] | ||
+ | [ ; ] | ||
+ | |||
+ | -- Applies to Azure SQL Data Warehouse and Parallel Data Warehouse Database | ||
+ | |||
+ | COMMIT [ TRAN | TRANSACTION ] | ||
+ | [ ; ] | ||
== 조건 == | == 조건 == | ||
+ | 트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적인 단위로 사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업 단위이다. 하나의 트랜잭션은 커밋(commit) 되거나 롤백이 된다.<ref name="트랜잭션">코딩팩토리, 〈[https://coding-factory.tistory.com/226 (DB기초) 트랜잭션이란 무엇인가?]〉, 《티스토리》, 2018-08-20</ref> [[데이터베이스]]의 트랜잭션이 안전하게 수행되기 위해서는 ACID 조건을 충족해야 한다. ACID란 Atomicity(원자성), Consistency(일관성), Isolation(고립성), Durability(지속성)의 약자로서, 데이터베이스의 트랜잭션이 안전하게 수행되기 위한 4가지 필수적인 성질을 말한다. | ||
+ | |||
+ | === 원자성 === | ||
+ | 원자성(atomicity)은 하나의 트랜잭션이 더 이상 작게 쪼갤 수 없는 최소한의 업무 단위이다. 트랜잭션이 데이터베이스에 모두 반영되던지, 아니면 전혀 반영되지 않아야 하며 작업이 부분적으로 실행되거나 중단되지 않는 것을 보장하는 것으로 즉, All or Nothing의 개념으로서 작업 단위를 일부분만 실행하지 않는다는 것을 의미한다. 트랜잭션 실행 도중 문제가 발생했을 경우 중단된 상태가 아닌 모두 실패하거나, 모두 완성되거나 둘 중 하나의 상태가 되어야 한다. 즉, 100개 명령어로 구성된 트랜잭션 중 99개 완료 1개 실패가 된다면, 이는 무조건 실패로 간주하여 트랜잭션 시작 전 상태로 돌려야 한다. 또한 100개가 모두 성공했을 시 트랜잭션은 성공이기 때문에 중간 상태가 없다. 트랜잭션은 사람이 설계한 논리적인 작업 단위이기 때문에 일처리가 작업 단위 별로 이루어져야 사람이 다루는데 무리가 없다. 만약 트랜잭션 단위로 데이터가 처리되지 않는다면, 설계한 사람은 데이터 처리 시스템을 이해하기 힘들 뿐만 아니라, 오작동 했을 시 원인을 찾기가 매우 힘들어진다. 트랜잭션 내의 모든 명령은 반드시 완벽하게 수행되어야 하며, 모두가 완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다. 트랜잭션이 원자성이라는 성질을 지니게 된 이유는 중간에 끊기게 되면 이후 해당 트랜잭션의 어디서부터 이어서 수행되어야 하는지 모르기 때문이다.<ref name="트랜잭션 성질2">victolee, 〈[https://victorydntmd.tistory.com/129 (DB이론) 트랜잭션(transaction)과 ACID 특성을 보장하는 방법]〉, 《티스토리》, 2018-02-09</ref><ref name="트랜잭션"/><ref name="트랜잭션 성질">Mommoo, | ||
+ | 〈[https://mommoo.tistory.com/62 트랜잭션(Transaction)이란?]〉, 《티스토리》, 2017-02-27</ref><ref name="트랜잭션 성질3">Lim-Ky, 〈[https://limkydev.tistory.com/100 (DataBase) 트랜잭션이란? (Transaction)]〉, 《티스토리》, 2017-10-06</ref><ref name="트랜잭션 성질4">망나니 개발자, 〈[https://mangkyu.tistory.com/30 (Database) 8. 트랜잭션, 동시성 제어, 회복]〉, 《티스토리》, 2017-12-12</ref> | ||
+ | |||
+ | * '''원자성 보장''' : 트랜잭션에서 원자성은 수행하고 있는 트랜잭션에 의해 변경된 내역을 유지하면서, 이전에 커밋된 상태를 임시 영역에 따로 저장함으로써 보장한다. 즉, 현재 수행하고 있는 트랜잭션에서 오류가 발생하면 현재 내역을 날려버리고 임시 영역에 저장했던 상태로 롤백 한다. 이전 데이터들이 임시로 저장되는 영역을 롤백 세그먼트(rollback segment)라고 하며, 현재 수행하고 있는 트랜잭션에 의해 새롭게 변경되는 내역을 데이터베이스 테이블이라고 한다. 다시 말해, 트랜잭션의 원자성은 롤백 세그먼트에 의해 보장된다고 할 수 있다. 그런데 오류가 발생하면 롤백 하는데, 트랜잭션의 길이가 길어지게 되면 확실하게 오류가 발생하지 않는 부분도 다시 처음부터 작업을 수행해야 한다. 따라서 확실한 부분에 대해서는 롤백이 되지 않도록 중간 저장 지점인 세이브포인트(save point)를 지정할 수 있다. 세이브포인트를 지정하게 되면 롤백 할 때 세이브포인트 이전은 확실하다 간주하고 그 이후부터 진행하게 된다.<ref name="트랜잭션 성질2"/> | ||
+ | |||
+ | === 일관성 === | ||
+ | 일관성(consistency)은 트랜잭션이 완료된 결괏값이 일관적인 DB 상태를 유지하는 것을 말한다. 시스템이 가지고 있는 고정요소는 수행 전과 후의 상태가 같아야 하며 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것으로 트랜잭션이 진행되는 동안 데이터베이스가 변경되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는 것이 아니라, 처음 트랜잭션을 진행하기 위해 참조한 데이터베이스로 진행된다. 이렇게 함으로써 각 사용자가 일관성 있는 데이터를 볼 수 있는 것이다. 트랜잭션 수행 전후의 데이터베이스 상태는 각각 일관성이 보장되는 서로 다른 상태가 된다. 트랜잭션 수행이 보존해야 할 일관성은 기본 키, 외래 키 제약과 같은 명시적인 [[무결성]] 제약 조건들뿐만 아니라, A에서 B로 돈을 이체할 때 A와 B 계좌의 돈의 총합이 같아야 한다는 사항과 같은 비명시적인 일관성 조건들도 있다.<ref name="트랜잭션 성질2"/><ref name="트랜잭션"/><ref name="트랜잭션 성질"/><ref name="트랜잭션 성질3"/><ref name="트랜잭션 성질4"/><ref name="트랜잭션 성질5">kmmguumnn, 〈[https://starkying.tistory.com/entry/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98Transaction%EC%9D%B4%EB%9E%80 트랜잭션(Transaction)이란?]〉, 《티스토리》, 2019-03-03</ref> | ||
+ | |||
+ | * '''일관성 보장''' : 트랜잭션에서 일관성은 트랜잭션 수행 전/후에 데이터 모델의 모든 제약 조건(기본 키, 외래 키, 도메인, 도메인 제약조건 등)을 만족하는 것을 통해 보장한다. 예를 들어 Movie와 Video 테이블이 있을 때 Video 테이블의 기본 키(primary key)인 movie_id가 외래키로 존재한다고 가정한다. 만약 movie_id의 제약 조건이 Movie 테이블에서 변경되면, Video 테이블에서도 movie_id가 변경되어야 한다. 한 쪽의 테이블에서만 데이터 변경사항이 이루어져서는 안되는 것이다. 이때 트랜잭션의 일관성을 보장하기 위한 방법은 어떤 이벤트와 조건이 발생했을 때, 트리거(Trigger)를 통해 보장하는 것이다. 트리거는 '방아쇠'라는 뜻인데, 데이터베이스 시스템이 자동적으로 수행할 동작을 명시할 때 사용된다. 즉, 어떤 행위의 시작을 알리는 것이다.<ref name="트랜잭션 성질2"/> | ||
+ | |||
+ | === 고립성 === | ||
+ | 고립성(isolation)이란 하나의 트랜잭션 수행시 다른 트랜잭션의 작업이 끼어들지 못하도록 보장하는 것이다. 즉, 트랜잭션 끼리는 서로를 간섭할 수 없다. 트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못하게 하는 특성이다. 데이터베이스는 클라이언트들이 같은 데이터를 공유하는 것이 목적이므로 여러 트랜잭션이 동시에 수행되어야 한다. 이때 트랜잭션은 상호 간의 존재를 모르고 독립적으로 수행되어야 한다. 고립성은 격리성이라고도 하는데 이를 유지하기 위해서는 여러 트랜잭션이 동시에 접근하는 데이터에 대한 제어가 필요하다. 여러 트랜잭션이 동시에 수행되더라도 각각의 트랜잭션은 다른 트랜잭션의 수행에 영향을 받지 않고 독립적으로 수행되어야 한다. 한 트랜잭션에서 데이터베이스를 변경한 내용은 트랜잭션이 커밋되기 전까지는 다른 어떤 질의나 트랜잭션과도 고립되어야만 한다. 즉, 각 트랜잭션은 시스템 내에서 동시에 수행되고 있는 다른 트랜잭션들을 알지 못하는 것이다. 한 트랜잭션의 중간 결과가 다른 트랜잭션에게는 숨겨져야 한다는 의미인데, 이러한 성질이 보장되지 않으면 트랜잭션이 원래 상태로 되돌아갈 수 없게 된다. DBMS의 병행 제어 모듈이 트랜잭션의 고립성을 보장하며 예를 들어 설명하자면 하나의 트랜잭션이 A라는 계좌에서 작업을 하고 있을 경우 다른 트랜잭션이 A계좌에 대해 참조하거나 관여할 수 없고 작업이 끝날 때까지 대기해야 하는 것을 말한다.<ref name="트랜잭션 성질2"/><ref name="트랜잭션 성질3"/><ref name="트랜잭션 성질4"/><ref name="트랜잭션 성질5"/> | ||
− | [[데이터베이스]] | + | * '''고립성 보장''' : 병행처리 과정에서 트랜잭션의 고립성이 왜 보장되어야 하는지 알 수 있다. OS의 세마포어(semaphore)와 비슷한 개념으로 lock&excute unlock을 통해 고립성을 보장할 수 있었다. 즉, 데이터를 거나 쓸 때는 문을 잠궈서 다른 트랜잭션이 접근하지 못하도록 고립성을 보장하고, 수행을 마치면 언락(unlock)을 통해 데이터를 다른 트랜잭션이 접근할 수 있도록 허용하는 방식이다. 트랜잭션에서는 데이터를 읽을 때, 여러 트랜잭션이 읽을 수는 있도록 허용하는 공유 록(shared_lock)을 한다. 즉, 공유 록은 데이터 쓰기를 허용하지 않고 오직 읽기만 허용하는 것이다. 또한 데이터를 쓸 때는 다른 트랜잭션이 읽을 수도 쓸 수도 없도록 하는 배타 록(exclusive_lock)을 사용한다. 그리고 읽기, 쓰기 작업이 끝나면 언락을 통해 다른 트랜잭션이 록(lock)을 할 수 있도록 데이터에 대한 잠금을 풀어준다. 단, 록(lock)과 언락을 잘못 사용하면 데드락(deadlock)상태에 빠질 수 있다. 즉, 모든 트랜잭션이 아무것도 수행할 수 없는 상태가 되는 것이다.<ref name="트랜잭션 성질2"/> |
− | * ''' | + | |
− | * ''' | + | === 지속성 === |
− | * ''' | + | 트랜잭션이 정상적으로 종료된 다음에는 영구적으로 데이터베이스에 작업의 결과가 저장되어야 한다. 지속성(durability)은 트랜잭션의 성공 결과 값은 장애 발생 후에도 변함없이 보관되어야 한다는 것으로 트랜잭션이 정상적으로 완료된 경우에는 버퍼의 내용을 하드디스크(데이터베이스)에 확실히 기록해야 하며, 부분 완료(Partial Commit)된 경우에는 작업을 취소(Aborted)하여야 한다 즉, 정상적으로 완료 혹은 부분 완료된 데이터는 DBMS가 책임지고 데이터베이스에 기록하는 성질이 지속성이며 영속성이라고 표현하기도 한다. |
− | * ''' | + | <ref name="트랜잭션 성질3"/><ref name="트랜잭션 성질4"/><ref name="트랜잭션 성질5"/> |
+ | |||
+ | ==특징== | ||
+ | === 무정지성 === | ||
+ | 트랜잭션 기능의 대표적인 이점 중 하나는 무정지성의 향상이다. 즉, [[운영체제]] [[장애 (정보통신)|장애]] 등의 서버 장애가 발생하여 그로부터 데이터베이스를 재가동한 때에 '장애 직전까지의 커밋 결과를 손실하지 않고 마치는 것'이 가능하다. 트랜잭션을 지원하지 않는 데이터베이스의 경우 OS 장애뿐만 아니라 데이터베이스 프로세스가 비정상적으로 종료하기만 해도 데이터베이스가 손상될 수 있다. 깨진 데이터베이스를 복구하려고 해도 일부 데이터가 없어지거나 완전히 복구되지 않는 등 완전한 회복이 불가능한 경우도 많다. [[오라클]](Oracle)과 InnoDB 같은 트랜잭션 대응의 데이터베이스에서는 이러한 문제가 발생하지 않는데, REDO 로그(데이터베이스에서 수행한 작업을 다시 실행하는 로그)를 이용한 아키텍처로 무정지성을 보장하고 있기 때문이다. | ||
+ | |||
+ | * '''REDO 로그''' : 열 값과 인덱스를 갖는 데이터 파일에는 커밋을 할 때마다 기록을 하는 것이 아니라 캐시 영역에 보관해 두고 정기적으로 디스크에 기록하는 동작을 하는데 REDO 로그 파일이 최신 커밋 정보를 가지고 있는 반면, 본체의 데이터 파일은 오래된 데이터를 가지고 있게 된다. 그래도 캐시 영역에 최신 데이터가 있기 때문에 데이터 파일에 이전 데이터밖에 없더라도 애플리케이션에서 보면 최신 데이터를 읽고 쓸 수 있어 모순된 상태가 되지는 않는다. 서버 장애 등의 이유로 데이터베이스가 멈춰서 재기동을 하게 되는 경우 데이터 파일이 이전 데이터밖에 남지 않았을 때 REDO 로그의 내용을 데이터 파일에 적용시켜 나감으로써 데이터 파일과 REDO 로그의 LSN과 일치시키는 작업을 수행한다. 이 과정을 충돌 복구(Clash Recovery)라고 한다. | ||
+ | |||
+ | ==과정== | ||
+ | [[파일:트랜잭션의 필요성.png|500픽셀|섬네일|트랜잭션의 필요성]] | ||
+ | [[파일:트랜잭션의 상태.png|500픽셀|섬네일|트랜잭션의 상태]] | ||
+ | [[파일:커밋(COMMIT).png|500픽셀|섬네일|커밋(commit)]] | ||
+ | [[파일:롤백(ROKKBACK).png|500픽셀|섬네일|롤백(rollback)]] | ||
+ | |||
+ | 트랜잭션은 거래의 안전성을 확보하는 방법이다. A 은행에서 B 은행으로 송금을 하다가 송금 도중 알 수 없는 오류가 발생하여 A 은행 계좌에서 돈이 빠져 나갔는데 B 은행 계좌에 입금되지 않았다. 이때, A 은행 계좌의 출금을 취소하거나 출금된 금액만큼 B 은행 계좌로 다시 송금하면 된다. 하지만 이러한 방법은 번거롭고 더 심한 오류를 발생시킬 수 있다. 이때 거래가 성공적으로 모두 끝난 후에야 이를 완전한 거래로 승인하고, 거래 도중 오류가 발생했을 때는 이 거래를 아예 처음부터 없었던 거래로 되돌려 이러한 문제를 예방할 수 있다. | ||
+ | |||
+ | 이렇게 거래의 안전성을 확보하는 방법이 바로 트랜잭션이다. 데이터베이스에서는 테이블에서 데이터를 읽어온 후 다른 테이블에 데이터를 입력하거나 갱신, 삭제하는 데 처리 도중 오류가 발생하면 모든 작업을 원상태로 되돌린다. 데이터베이스에서는 처리 과정이 모두 성공했을 때만 최종적으로 데이터베이스에 반영한다. 1, 2번까지 잘 실행되다가 3번 작업 시 소프트웨어가 중단되거나 하드웨어 고장이 발생해 작업에 오류가 생기게 된다면 2번까지의 모든 작업을 취소하고 트랜잭션 작업 전인 데이터베이스 초기 상태로 돌아가게 된다.<ref name="트랜잭션2">쩨리쩨리, 〈[https://jerryjerryjerry.tistory.com/48 (SQL) Transaction(트랜잭션)]〉, 《티스토리》, 2018-04-24</ref> | ||
+ | |||
+ | ===상태=== | ||
+ | 트랜잭션에는 사용자가 적은 쿼리문과 데이터를 최종적으로 데이터베이스에 반영하는 커밋과 실패했을 때 시점으로 다시 되돌아가는 롤백이 있다. | ||
+ | * '''활동'''(Active) : 트랜잭션이 실행 중인 상태이다. | ||
+ | * '''실패'''(Failed) : 트랜잭션 실행에 오류가 발생하여 중단된 상태이다. | ||
+ | * '''철회'''(Aborted) : 트랜잭션이 비정상적으로 종료되어 롤백 연산을 수행한 상태이다. | ||
+ | * '''부분 완료'''(Partially Committed) : 트랜잭션의 마지막 연산까지 실행했지만, 커밋 연산이 실행되기 직전의 상태이다. | ||
+ | * '''완료'''(Committed) : 트랜잭션이 성공적으로 종료되어 커밋 연산을 실행한 후의 상태이다.<ref name="트랜잭션"/> | ||
+ | |||
+ | === 연산 === | ||
+ | ==== 커밋 ==== | ||
+ | [[커밋]](commit) 연산은 모든 작업들을 정상적으로 처리하겠다고 확정하는 명령어로서, 처리과정을 데이터베이스에 영구적으로 저장하는 것이다. 커밋을 수행하면 하나의 트랜잭션 과정을 종료하는 것이다. 커밋을 수행하면 이전 데이터가 완전히 업데이트된다.<ref name="트랜잭션"/> 우측 그림에서 첫 번째 커밋 후 그 뒤에 Update 문으로 데이터를 갱신하고 Delete 문으로 데이터를 삭제한 후 Insert 문을 사용해 데이터를 삽입한다. 만약 이 모든 과정이 오류 없이 수행되었다면 지금까지 실행한 모든 작업을 데이터베이스에 영구 저장하라는 명령으로 커밋을 수행한다.<ref name="트랜잭션2"/> | ||
+ | |||
+ | ==== 롤백 ==== | ||
+ | [[롤백]](rollback) 연산은 작업 중 문제가 발생하여 트랜잭션의 처리과정에서 발생한 변경사항을 취소하는 명령어이다. 이 트랜잭션의 일부가 정상적으로 처리되더라도 트랜잭션의 원자성을 구현하기 위해 이 트랜잭션이 행한 모든 연산을 취소한다는 특징이 있다. 트랜잭션이 시작되기 이전의 상태로 되돌린다. 즉, 마지막 커밋을 완료한 시점으로 다시 돌아간다. 커밋하여 저장한 것만 복구한다. 롤백 시에는 해당 트랜잭션을 재시작하거나 폐기한다.<ref name="트랜잭션"/> 우측 그림에서 롤백 명령은 마지막으로 수행한 커밋 명령까지만 정상 처리된 상태로 유지한다. 그 이후에 수행했던 모든 DML 명령어 작업들을 취소시켜 이전 상태로 원상 복귀 시킨다. 트랜잭션은 이렇듯 all or nothing(모든 것을 수행하던지 아무것도 하지 말던지) 방식으로 DML 명령어들을 처리한다.<ref name="트랜잭션2"/> | ||
+ | |||
+ | ====세이브포인트==== | ||
+ | [[세이브포인트]](save point)는 '임시저장' 또는 '부분저장'과 같은 맥락으로 이해할 수 있다. 보통 롤백을 명시하면 삽입, 삭제, 업데이트 등의 작업 전체가 취소되는데, 세이브포인트는 전체가 아닌 특정 부분에서 트랜잭션을 취소하기 위해 사용한다. 세이브포인트를 쓰면 현재의 트랜잭션을 작게 분할하는 것이 가능하다. 세이브포인트는 여러 개의 [[에스큐엘]](SQL)문의 실행을 수행하는 트랜잭션의 경우에 사용자가 트랜잭션 중간 단계에서 세이브포인트를 지정할 수 있다. 세이브포인트를 쓰려면 취소하려는 지점을 명시한 뒤, 그 지점까지 작업을 취소하는 식으로 사용하는데 이 지점을 세이브포인트라고 한다. 세이브포인트를 지정한 뒤 롤백 투 세이브포인트 이름;(rollback to save point name;)을 실행하면 해당 세이브포인트 지점까지 처리한 직업이 [[롤백]]된다. | ||
+ | |||
+ | == 스케줄 종류 == | ||
+ | === 직렬 스케줄 === | ||
+ | 직렬 스케줄(Serial schedule)은 순서대로, 하나씩 트랜잭션을 실행하는 것으로 트랜잭션 하나의 실행이 완료되면 다른 트랜잭션을 시작하는 방식으로 하나씩 차례대로 실행하는 스케줄로서 트랜잭션이 실행되는 동안 다른 트랜잭션의 영향을 받을 수 없으므로 모순이 발생하지 않는다.<ref name="트랜잭션3"/> | ||
+ | |||
+ | === 직렬화 스케줄 === | ||
+ | 직렬화 스케줄(Serializable schedule)은 병행 제어, 직렬 스케줄 장점을 가진 것으로 트랜잭션들이 동시에 자료 접근 연산들을 교차하며 실행시키면서도 결과가 직렬 스케줄과 동일한 스케줄이다. 즉, 병행 처리하지만 적절한 제어 조치를 취함으로써 일관성을 유지하는 스케줄로서 병행 제어에서 필요한 스케줄이다. 즉, 병행 제어 스케줄은 직렬성을 유지할 수 있다. 직렬성이란 트랜잭션들의 처리 결과가 직렬 처리와 동일한 효과를 가지는 스케줄 특성이다.<ref name="트랜잭션3"/> | ||
+ | |||
+ | == 병행처리 == | ||
+ | 다수의 사용자가 데이터베이스에 요청을 보내게 되면 이러한 요청들을 처리할 방법이 필요하다. 만약 하나의 요청을 끝내고 다른 요청을 수행하는 방식이라면 처리시간이 매우 오래 걸린다. 그래서 병행처리 방식으로 처리를 한다. 트랜잭션을 병행처리하면 처리 효율이 높아지지만, 처리 과정에서 동일한 자료를 동시에 접근해서 오류가 생길 수 있다. | ||
+ | :{|class=wikitable width=700 style="background-color:white; margin:0 auto;" | ||
+ | |+병행처리의 문제점 | ||
+ | !align=center style="background-color:ashgray"|종류 | ||
+ | !align=center style="background-color:ashgray"|내역 | ||
+ | !align=center style="background-color:ashgray"|문제점 | ||
+ | |- | ||
+ | |align=center|갱신 유실 문제 | ||
+ | |align=center|두 트랜잭션이 동시에 동일한 자료를 갱신 | ||
+ | |align=center|첫째 갱신이 유실 | ||
+ | |- | ||
+ | |align=center|오류 읽기 문제 | ||
+ | |align=center|갱신하는 도중에 다른 트랜잭션이 읽기 | ||
+ | |align=center|낡은 자료 읽기 | ||
+ | |- | ||
+ | |align=center|잘못된 요약 | ||
+ | |align=center|두 자료를 갱신하는 도중에 읽기 | ||
+ | |align=center|요약 결과 오류 | ||
+ | |- | ||
+ | |align=center|무결성 제약조건 | ||
+ | |align=center|두 자료의 제약조건을 검사하지 않고 갱신 | ||
+ | |align=center|일관성 위반 | ||
+ | |} | ||
+ | |||
+ | 따라서 병행제어가 필요한데, 병행제어가 필요한 이유는 다음과 같다. | ||
+ | * '''분실된 업데이트 문제'''(The Lost Update Problem) : 두 개의 트랜잭션이 동일한 아이템에 접근하여 서로의 연산이 중첩될 때 결과적으로 올바르지 않은 값이 저장될 수 있다. | ||
+ | * '''임시 업데이트 문제'''(The Temporary Update Problem) : 한 트랜잭션이 값을 업데이트하다가 중간에 트랜잭션이 실패하였다. 하지만 롤백하기 이전에 다른 트랜잭션이 값을 읽게 되면 올바르지 않은 값을 읽는 것이다. | ||
+ | * '''잘못된 요약 문제'''(The Incorrect Summary Problem) : 한 트랜잭션이 aggregate 함수(Sum, Max, Min 등)를 실행하고 있는데, 다른 트랜잭션이 이 값들 중 하나를 업데이트하고 있을 때 aggregate 트랜잭션의 값이 업데이트되기 이전을 사용할 때이다. | ||
+ | |||
+ | 데이터베이스 병행처리의 목적은 1) 트랜잭션의 충돌을 방지하기 위해 고립성을 강제하기 위함, 2) 데이터베이스의 일관성을 보존하기 위함, 3) read-write 또는 write-write 충돌을 막기 위함의 세 가지로서, 스케줄의 진정한 목적은 충돌 스케줄을 찾아 직렬화 스케줄을 만드는 것이다.<ref name="트랜잭션3">jhkang-dev, 〈[https://jhkang-tech.tistory.com/103 (데이터베이스) 트랜잭션]〉, 《티스토리》, 2018-11-28</ref> | ||
+ | |||
+ | == 록킹 == | ||
+ | 트랜잭션이 자료를 배타적으로 접근할 수 있으면 그 트랜잭션이 완료된 후에 다른 트랜잭션이 실행되기 때문에 직렬성이 확보된다. 자료를 배타적으로 접근하는 방법이 바로 록킹 기법이다. 트랜잭션의 ACID 특성을 해치는 접근 연산은 주로 갱신이다. 읽기 연산은 자료 값을 바꾸지 않는다. 하지만 읽기 연산 도중에 갱신을 하게되면 일관성 유지가 어려울 수 있다. 트랜잭션에는 공유 록과 배타 록 2가지가 있다. | ||
+ | * '''공유 록''' : 특정 자료 Q에 공유 록을 걸면 다른 트랜잭션이 이 자료를 갱신할 수 없다. 공유 록(Shared Lock)이 걸린 Q는 다른 트랜잭션에 의해서 읽혀질 수 있다.<ref name="트랜잭션3"/> | ||
+ | * '''배타 록''' : 트랜잭션이 자료를 기록할 때 배타 록(Exclusive Lock) X를 걸어야 한다. 록 X를 가진 트랜잭션은 자료를 읽을 수도 있고, 갱신할 수도 있다. 배타 록 X가 걸린 자료는 공유 록 S를 가진 트랜잭션들에 의해서 읽혀질 수 없는데 더디리드(Dirty Read)를 방지하기 위해서이다.<ref name="트랜잭션3"/> | ||
+ | |||
+ | == 복제 == | ||
+ | 복제 구성에서 있어서 [[슬레이브]]에서는 [[마스터]]에서 전송되어 온 업데이트성 [[쿼리]]를 실행하는 역할을 한다. 이 처리는 사실 업데이트성 쿼리를 실행하는 것만으로는 충분하지 않고 슬레이브는 마스터에서 보낸 업데이트성 쿼리 중에서 어디까지를 실행했는지라는 정보도 관리할 필요가 있다. 그렇게 처리하지 않으면 도중에 슬레이브가 멈추었을 경우 어디서부터 다시 시작하면 좋을지 알 수 없기 때문이다. 엄밀하게는 이 정보원들은 동일한 트랜잭션에서 원자성 있게 갱신해야 한다. [[마이에스큐엘]](MySQL)에서는 마스터가 트랜잭션이 커밋될 때마다 그 생신 에스큐엘(SQL) 문을 바이너리 로그에 기록할 때, 슬레이브에서는 바이너리 로그의 내용을 싫어하여 나가지만, 현재 어디까지 실행했는지를 관리하기 위해 실행을 마친 바이너리 로그의 위치 정보를 관리하는 InnoDB 테이블을 제공한다. 그리고 갱신 에스큐엘 문의 실행과 위치 정보 갱신을 동일한 트랜잭션에서 실시한다. 애플리케이션의 관점에서 모든 업데이트성 쿼리가 UPDATE 문 한 번밖에 없는 자동 커밋 쿼리라 할지라도 복제 구성과 조합한 시점에서 업데이트성 쿼리의 실행에 더하여 복제 상태 업데이트 처리도 모두 한 개의 트랜잭션으로 하지 않으면 안된다. 이것들이 하나의 트랜잭션으로 되어 있으면 어느 타이밍에 크래쉬해도 갱신 확정된 쿼리를 또다시 복제하거나, 반대로 복제를 날려 버리는 일은 없게 될 것이다. | ||
+ | |||
+ | == 블록체인 == | ||
+ | [[파일:트랜잭션블록체인.png|800픽셀|섬네일|가운데|블록체인에서의 트랜잭션]] | ||
+ | |||
+ | [[블록체인]]은 트랜잭션을 [[블록]](Block) 단위의 [[체인]](Chain) 형태로 저장하는 기술이다. 블록체인 상 저장 데이터는 트랜잭션 단위로 생성되게 된다. 트랜잭션은 일반적으로 이전 트랜잭션 출력을 새 트랜잭션 입력으로 참조하고 모든 입력 [[비트코인]](Bitcoin) 값을 새 출력으로 바치는 구조이다. 또한, 트랜잭션은 이중 입력 부기 장부의 연결과 같다. 소유자 [[디지털 서명]]을 사용하여 값을 소비하는 비트코인의 각 금액에 대한 소유권 증명이 포함되어 있으며, 이는 누구든지 독립적으로 확인할 수 있다. 블록은 트랜잭션의 집합을 블록 단위로 기록하며 [[채굴]] 행위를 통해 약 10분(상황에 따라 다름)을 주기로 발행된다. 즉, 블록은 이전 블록의 [[해시 값]](ID)를 포함한다. 블록은 일종의 데이터 패킷으로 위 그림과 같이 몇 가지 정보들을 담고 있다. 가장 중요한 것으로 참여자들이 화폐를 거래한 거래내역, 그리고 이전 블록의 해시 값, [[채굴 난이도]], [[논스]](Nonce) 등이 포함된다. 매 블록은 바로 전 블록의 해시값을 담고 있으며, 이렇게 이어진 블록들은 시간순으로 발생한 이체 내역들을 담고 있는 하나의블록체인을 이룬다.<ref>kimjunyong, 〈[https://medium.com/@kimjunyong/%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%9D%98-%EC%A0%95%EC%9D%98%EC%99%80-%EA%B8%B0%EC%88%A0-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EA%B8%B0%EB%B3%B8%EC%A0%81-%EC%9D%B4%ED%95%B4-6706ebb43009 블록체인의 정의와 기술 비전공자도 이해하는 기본적 이해]〉, 《미디움》, 2018-11-13</ref> | ||
+ | |||
+ | {{각주}} | ||
+ | |||
+ | == 참고자료 == | ||
+ | * 데이터베이스 트랜잭션 위키백과 - https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98 | ||
+ | * 마이크로소프트 BEGIN TRANSACTION(Transact-SQL) - https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/begin-transaction-transact-sql?view=sql-server-ver15 | ||
+ | * 마이크로소프트 COMMIT TRANSACTION(Transact-SQL) - https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/commit-transaction-transact-sql?view=sql-server-ver15 | ||
+ | * 코딩팩토리, 〈[https://coding-factory.tistory.com/226 (DB기초) 트랜잭션이란 무엇인가?]〉, 《티스토리》, 2018-08-20 | ||
+ | * Mommoo, 〈[https://mommoo.tistory.com/62 트랜잭션(Transaction)이란?]〉, 《티스토리》, 2017-02-27 | ||
+ | * victolee, 〈[https://victorydntmd.tistory.com/129 (DB이론) 트랜잭션(transaction)과 ACID 특성을 보장하는 방법]〉, 《티스토리》, 2018-02-09 | ||
+ | * Lim-Ky, 〈[https://limkydev.tistory.com/100 (DataBase) 트랜잭션이란? (Transaction)]〉, 《티스토리》, 2017-12-12 | ||
+ | * 망나니 개발자, 〈[https://mangkyu.tistory.com/30 (Database) 8. 트랜잭션, 동시성 제어, 회복]〉, 《티스토리》, 2017-10-06 | ||
+ | * kmmguumnn, 〈[https://starkying.tistory.com/entry/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98Transaction%EC%9D%B4%EB%9E%80 트랜잭션(Transaction)이란?]〉, 《티스토리》, 2019-03-03 | ||
+ | * 쩨리쩨리, 〈[https://jerryjerryjerry.tistory.com/48 (SQL) Transaction(트랜잭션)]〉, 《티스토리》, 2018-04-24 | ||
+ | * jhkang-dev, 〈[https://jhkang-tech.tistory.com/103 (데이터베이스) 트랜잭션]》, 2018-11-28 | ||
+ | * kimjunyong, 〈[https://medium.com/@kimjunyong/%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8%EC%9D%98-%EC%A0%95%EC%9D%98%EC%99%80-%EA%B8%B0%EC%88%A0-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EB%8F%84-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EA%B8%B0%EB%B3%B8%EC%A0%81-%EC%9D%B4%ED%95%B4-6706ebb43009 블록체인의 정의와 기술 비전공자도 이해하는 기본적 이해]〉, 《미디움》, 2018-11-13 | ||
== 같이 보기 == | == 같이 보기 == | ||
* [[데이터베이스]] | * [[데이터베이스]] | ||
+ | * [[블록체인]] | ||
+ | * [[TPS]] | ||
+ | * [[커밋]] | ||
+ | * [[롤백]] | ||
− | + | {{데이터|검토 필요}} | |
− |
2022년 12월 19일 (월) 17:38 기준 최신판
트랜잭션(transaction)이란 "쪼갤 수 없는 업무 처리의 최소 단위"를 말한다. 거래내역이라고도 한다. '트렌젝션'이 아니라 '트랜잭션'이 올바른 표기법이다. 영어로 간략히 Tx라고 표기하기도 한다. 1초당 처리할 수 있는 트랜잭션의 개수를 TPS라고 한다.
목차
개요[편집]
트랜잭션은 은행 ATM이나 데이터베이스 등의 시스템에서 사용되는 더 이상 쪼갤 수 없는 업무 처리의 최소 단위이다. 예를 들어, A라는 사람이 B라는 사람에게 1,000원을 지급하고 B가 그 돈을 받은 경우, 이 거래 기록은 더 이상 작게 쪼갤 수가 없는 하나의 트랜잭션을 구성한다. 만약 A는 돈을 지불했으나 B는 돈을 받지 못했다면 그 거래는 성립되지 않는다. 이처럼 A가 돈을 지불하는 행위와 B가 돈을 받는 행위는 별개로 분리될 수 없으며 하나의 거래내역으로 처리되어야 하는 단일 거래이다. 이런 거래의 최소 단위를 트랜잭션이라고 한다. 트랜잭션 처리가 정상적으로 완료된 경우 커밋(commit)을 하고, 오류가 발생할 경우 원래 상태대로 롤백(rollback)을 한다.
목적[편집]
트랜잭션은 데이터베이스 서버에 여러 개의 클라이언트가 동시에 액세스 하거나 응용프로그램이 갱신을 처리하는 과정에서 중단될 수 있는 경우 등 데이터 부정합을 방지하고자 할 때 사용한다.[1] 데이터베이스 기능 중, 트랜잭션을 조작하는 기능은 데이터베이스 완전성(integrity) 유지를 확신하게 한다. 단일 트랜잭션은 데이터베이스 내에 읽거나 쓰는 여러 개 쿼리를 요구한다. 이때 중요한 것은 데이터베이스가 수행된 일부 쿼리가 남지 않는 것이다. 예를 들어, 송금을 할 때 한 계좌에서 인출되면 다른 계좌에서 입금이 확인되는 것이 중요하다. 또한 트랜잭션은 서로 간섭하지 않아야 한다. 만약 쿼리 하나가 실패하면, 데이터베이스 시스템은 전체 트랜잭션 또는 실패한 쿼리를 롤백 한다. 이것은 DBMS가 어떻게 사용되고 셋업 되었느냐에 따라 다르다. 트랜잭션은 커밋전에 언제든지 수동으로 롤백 될 수 있다. 간단한 트랜잭션의 경우 아래 양식의 SQL 언어로 데이터베이스 내에서 실행된다.[2]
- Begin the transaction[3]
--Applies to SQL Server and Azure SQL Database BEGIN { TRAN | TRANSACTION } [ { transaction_name | @tran_name_variable } [ WITH MARK [ 'description' ] ] ] [ ; ]
--Applies to Azure SQL Data Warehouse and Parallel Data Warehouse BEGIN { TRAN | TRANSACTION } [ ; ]
- Execute several queries(DB내 갱신이 아직 적용되지 않는다.)
- Commit the transaction(트랜잭션이 성공적이며, 갱신이 실제 적용됨.)[4]
-- Applies to SQL Server (starting with 2008) and Azure SQL Database COMMIT [ { TRAN | TRANSACTION } [ transaction_name | @tran_name_variable ] ] [ WITH ( DELAYED_DURABILITY = { OFF | ON } ) ] [ ; ]
-- Applies to Azure SQL Data Warehouse and Parallel Data Warehouse Database COMMIT [ TRAN | TRANSACTION ] [ ; ]
조건[편집]
트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적인 단위로 사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업 단위이다. 하나의 트랜잭션은 커밋(commit) 되거나 롤백이 된다.[5] 데이터베이스의 트랜잭션이 안전하게 수행되기 위해서는 ACID 조건을 충족해야 한다. ACID란 Atomicity(원자성), Consistency(일관성), Isolation(고립성), Durability(지속성)의 약자로서, 데이터베이스의 트랜잭션이 안전하게 수행되기 위한 4가지 필수적인 성질을 말한다.
원자성[편집]
원자성(atomicity)은 하나의 트랜잭션이 더 이상 작게 쪼갤 수 없는 최소한의 업무 단위이다. 트랜잭션이 데이터베이스에 모두 반영되던지, 아니면 전혀 반영되지 않아야 하며 작업이 부분적으로 실행되거나 중단되지 않는 것을 보장하는 것으로 즉, All or Nothing의 개념으로서 작업 단위를 일부분만 실행하지 않는다는 것을 의미한다. 트랜잭션 실행 도중 문제가 발생했을 경우 중단된 상태가 아닌 모두 실패하거나, 모두 완성되거나 둘 중 하나의 상태가 되어야 한다. 즉, 100개 명령어로 구성된 트랜잭션 중 99개 완료 1개 실패가 된다면, 이는 무조건 실패로 간주하여 트랜잭션 시작 전 상태로 돌려야 한다. 또한 100개가 모두 성공했을 시 트랜잭션은 성공이기 때문에 중간 상태가 없다. 트랜잭션은 사람이 설계한 논리적인 작업 단위이기 때문에 일처리가 작업 단위 별로 이루어져야 사람이 다루는데 무리가 없다. 만약 트랜잭션 단위로 데이터가 처리되지 않는다면, 설계한 사람은 데이터 처리 시스템을 이해하기 힘들 뿐만 아니라, 오작동 했을 시 원인을 찾기가 매우 힘들어진다. 트랜잭션 내의 모든 명령은 반드시 완벽하게 수행되어야 하며, 모두가 완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다. 트랜잭션이 원자성이라는 성질을 지니게 된 이유는 중간에 끊기게 되면 이후 해당 트랜잭션의 어디서부터 이어서 수행되어야 하는지 모르기 때문이다.[1][5][6][7][8]
- 원자성 보장 : 트랜잭션에서 원자성은 수행하고 있는 트랜잭션에 의해 변경된 내역을 유지하면서, 이전에 커밋된 상태를 임시 영역에 따로 저장함으로써 보장한다. 즉, 현재 수행하고 있는 트랜잭션에서 오류가 발생하면 현재 내역을 날려버리고 임시 영역에 저장했던 상태로 롤백 한다. 이전 데이터들이 임시로 저장되는 영역을 롤백 세그먼트(rollback segment)라고 하며, 현재 수행하고 있는 트랜잭션에 의해 새롭게 변경되는 내역을 데이터베이스 테이블이라고 한다. 다시 말해, 트랜잭션의 원자성은 롤백 세그먼트에 의해 보장된다고 할 수 있다. 그런데 오류가 발생하면 롤백 하는데, 트랜잭션의 길이가 길어지게 되면 확실하게 오류가 발생하지 않는 부분도 다시 처음부터 작업을 수행해야 한다. 따라서 확실한 부분에 대해서는 롤백이 되지 않도록 중간 저장 지점인 세이브포인트(save point)를 지정할 수 있다. 세이브포인트를 지정하게 되면 롤백 할 때 세이브포인트 이전은 확실하다 간주하고 그 이후부터 진행하게 된다.[1]
일관성[편집]
일관성(consistency)은 트랜잭션이 완료된 결괏값이 일관적인 DB 상태를 유지하는 것을 말한다. 시스템이 가지고 있는 고정요소는 수행 전과 후의 상태가 같아야 하며 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것으로 트랜잭션이 진행되는 동안 데이터베이스가 변경되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는 것이 아니라, 처음 트랜잭션을 진행하기 위해 참조한 데이터베이스로 진행된다. 이렇게 함으로써 각 사용자가 일관성 있는 데이터를 볼 수 있는 것이다. 트랜잭션 수행 전후의 데이터베이스 상태는 각각 일관성이 보장되는 서로 다른 상태가 된다. 트랜잭션 수행이 보존해야 할 일관성은 기본 키, 외래 키 제약과 같은 명시적인 무결성 제약 조건들뿐만 아니라, A에서 B로 돈을 이체할 때 A와 B 계좌의 돈의 총합이 같아야 한다는 사항과 같은 비명시적인 일관성 조건들도 있다.[1][5][6][7][8][9]
- 일관성 보장 : 트랜잭션에서 일관성은 트랜잭션 수행 전/후에 데이터 모델의 모든 제약 조건(기본 키, 외래 키, 도메인, 도메인 제약조건 등)을 만족하는 것을 통해 보장한다. 예를 들어 Movie와 Video 테이블이 있을 때 Video 테이블의 기본 키(primary key)인 movie_id가 외래키로 존재한다고 가정한다. 만약 movie_id의 제약 조건이 Movie 테이블에서 변경되면, Video 테이블에서도 movie_id가 변경되어야 한다. 한 쪽의 테이블에서만 데이터 변경사항이 이루어져서는 안되는 것이다. 이때 트랜잭션의 일관성을 보장하기 위한 방법은 어떤 이벤트와 조건이 발생했을 때, 트리거(Trigger)를 통해 보장하는 것이다. 트리거는 '방아쇠'라는 뜻인데, 데이터베이스 시스템이 자동적으로 수행할 동작을 명시할 때 사용된다. 즉, 어떤 행위의 시작을 알리는 것이다.[1]
고립성[편집]
고립성(isolation)이란 하나의 트랜잭션 수행시 다른 트랜잭션의 작업이 끼어들지 못하도록 보장하는 것이다. 즉, 트랜잭션 끼리는 서로를 간섭할 수 없다. 트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못하게 하는 특성이다. 데이터베이스는 클라이언트들이 같은 데이터를 공유하는 것이 목적이므로 여러 트랜잭션이 동시에 수행되어야 한다. 이때 트랜잭션은 상호 간의 존재를 모르고 독립적으로 수행되어야 한다. 고립성은 격리성이라고도 하는데 이를 유지하기 위해서는 여러 트랜잭션이 동시에 접근하는 데이터에 대한 제어가 필요하다. 여러 트랜잭션이 동시에 수행되더라도 각각의 트랜잭션은 다른 트랜잭션의 수행에 영향을 받지 않고 독립적으로 수행되어야 한다. 한 트랜잭션에서 데이터베이스를 변경한 내용은 트랜잭션이 커밋되기 전까지는 다른 어떤 질의나 트랜잭션과도 고립되어야만 한다. 즉, 각 트랜잭션은 시스템 내에서 동시에 수행되고 있는 다른 트랜잭션들을 알지 못하는 것이다. 한 트랜잭션의 중간 결과가 다른 트랜잭션에게는 숨겨져야 한다는 의미인데, 이러한 성질이 보장되지 않으면 트랜잭션이 원래 상태로 되돌아갈 수 없게 된다. DBMS의 병행 제어 모듈이 트랜잭션의 고립성을 보장하며 예를 들어 설명하자면 하나의 트랜잭션이 A라는 계좌에서 작업을 하고 있을 경우 다른 트랜잭션이 A계좌에 대해 참조하거나 관여할 수 없고 작업이 끝날 때까지 대기해야 하는 것을 말한다.[1][7][8][9]
- 고립성 보장 : 병행처리 과정에서 트랜잭션의 고립성이 왜 보장되어야 하는지 알 수 있다. OS의 세마포어(semaphore)와 비슷한 개념으로 lock&excute unlock을 통해 고립성을 보장할 수 있었다. 즉, 데이터를 거나 쓸 때는 문을 잠궈서 다른 트랜잭션이 접근하지 못하도록 고립성을 보장하고, 수행을 마치면 언락(unlock)을 통해 데이터를 다른 트랜잭션이 접근할 수 있도록 허용하는 방식이다. 트랜잭션에서는 데이터를 읽을 때, 여러 트랜잭션이 읽을 수는 있도록 허용하는 공유 록(shared_lock)을 한다. 즉, 공유 록은 데이터 쓰기를 허용하지 않고 오직 읽기만 허용하는 것이다. 또한 데이터를 쓸 때는 다른 트랜잭션이 읽을 수도 쓸 수도 없도록 하는 배타 록(exclusive_lock)을 사용한다. 그리고 읽기, 쓰기 작업이 끝나면 언락을 통해 다른 트랜잭션이 록(lock)을 할 수 있도록 데이터에 대한 잠금을 풀어준다. 단, 록(lock)과 언락을 잘못 사용하면 데드락(deadlock)상태에 빠질 수 있다. 즉, 모든 트랜잭션이 아무것도 수행할 수 없는 상태가 되는 것이다.[1]
지속성[편집]
트랜잭션이 정상적으로 종료된 다음에는 영구적으로 데이터베이스에 작업의 결과가 저장되어야 한다. 지속성(durability)은 트랜잭션의 성공 결과 값은 장애 발생 후에도 변함없이 보관되어야 한다는 것으로 트랜잭션이 정상적으로 완료된 경우에는 버퍼의 내용을 하드디스크(데이터베이스)에 확실히 기록해야 하며, 부분 완료(Partial Commit)된 경우에는 작업을 취소(Aborted)하여야 한다 즉, 정상적으로 완료 혹은 부분 완료된 데이터는 DBMS가 책임지고 데이터베이스에 기록하는 성질이 지속성이며 영속성이라고 표현하기도 한다. [7][8][9]
특징[편집]
무정지성[편집]
트랜잭션 기능의 대표적인 이점 중 하나는 무정지성의 향상이다. 즉, 운영체제 장애 등의 서버 장애가 발생하여 그로부터 데이터베이스를 재가동한 때에 '장애 직전까지의 커밋 결과를 손실하지 않고 마치는 것'이 가능하다. 트랜잭션을 지원하지 않는 데이터베이스의 경우 OS 장애뿐만 아니라 데이터베이스 프로세스가 비정상적으로 종료하기만 해도 데이터베이스가 손상될 수 있다. 깨진 데이터베이스를 복구하려고 해도 일부 데이터가 없어지거나 완전히 복구되지 않는 등 완전한 회복이 불가능한 경우도 많다. 오라클(Oracle)과 InnoDB 같은 트랜잭션 대응의 데이터베이스에서는 이러한 문제가 발생하지 않는데, REDO 로그(데이터베이스에서 수행한 작업을 다시 실행하는 로그)를 이용한 아키텍처로 무정지성을 보장하고 있기 때문이다.
- REDO 로그 : 열 값과 인덱스를 갖는 데이터 파일에는 커밋을 할 때마다 기록을 하는 것이 아니라 캐시 영역에 보관해 두고 정기적으로 디스크에 기록하는 동작을 하는데 REDO 로그 파일이 최신 커밋 정보를 가지고 있는 반면, 본체의 데이터 파일은 오래된 데이터를 가지고 있게 된다. 그래도 캐시 영역에 최신 데이터가 있기 때문에 데이터 파일에 이전 데이터밖에 없더라도 애플리케이션에서 보면 최신 데이터를 읽고 쓸 수 있어 모순된 상태가 되지는 않는다. 서버 장애 등의 이유로 데이터베이스가 멈춰서 재기동을 하게 되는 경우 데이터 파일이 이전 데이터밖에 남지 않았을 때 REDO 로그의 내용을 데이터 파일에 적용시켜 나감으로써 데이터 파일과 REDO 로그의 LSN과 일치시키는 작업을 수행한다. 이 과정을 충돌 복구(Clash Recovery)라고 한다.
과정[편집]
트랜잭션은 거래의 안전성을 확보하는 방법이다. A 은행에서 B 은행으로 송금을 하다가 송금 도중 알 수 없는 오류가 발생하여 A 은행 계좌에서 돈이 빠져 나갔는데 B 은행 계좌에 입금되지 않았다. 이때, A 은행 계좌의 출금을 취소하거나 출금된 금액만큼 B 은행 계좌로 다시 송금하면 된다. 하지만 이러한 방법은 번거롭고 더 심한 오류를 발생시킬 수 있다. 이때 거래가 성공적으로 모두 끝난 후에야 이를 완전한 거래로 승인하고, 거래 도중 오류가 발생했을 때는 이 거래를 아예 처음부터 없었던 거래로 되돌려 이러한 문제를 예방할 수 있다.
이렇게 거래의 안전성을 확보하는 방법이 바로 트랜잭션이다. 데이터베이스에서는 테이블에서 데이터를 읽어온 후 다른 테이블에 데이터를 입력하거나 갱신, 삭제하는 데 처리 도중 오류가 발생하면 모든 작업을 원상태로 되돌린다. 데이터베이스에서는 처리 과정이 모두 성공했을 때만 최종적으로 데이터베이스에 반영한다. 1, 2번까지 잘 실행되다가 3번 작업 시 소프트웨어가 중단되거나 하드웨어 고장이 발생해 작업에 오류가 생기게 된다면 2번까지의 모든 작업을 취소하고 트랜잭션 작업 전인 데이터베이스 초기 상태로 돌아가게 된다.[10]
상태[편집]
트랜잭션에는 사용자가 적은 쿼리문과 데이터를 최종적으로 데이터베이스에 반영하는 커밋과 실패했을 때 시점으로 다시 되돌아가는 롤백이 있다.
- 활동(Active) : 트랜잭션이 실행 중인 상태이다.
- 실패(Failed) : 트랜잭션 실행에 오류가 발생하여 중단된 상태이다.
- 철회(Aborted) : 트랜잭션이 비정상적으로 종료되어 롤백 연산을 수행한 상태이다.
- 부분 완료(Partially Committed) : 트랜잭션의 마지막 연산까지 실행했지만, 커밋 연산이 실행되기 직전의 상태이다.
- 완료(Committed) : 트랜잭션이 성공적으로 종료되어 커밋 연산을 실행한 후의 상태이다.[5]
연산[편집]
커밋[편집]
커밋(commit) 연산은 모든 작업들을 정상적으로 처리하겠다고 확정하는 명령어로서, 처리과정을 데이터베이스에 영구적으로 저장하는 것이다. 커밋을 수행하면 하나의 트랜잭션 과정을 종료하는 것이다. 커밋을 수행하면 이전 데이터가 완전히 업데이트된다.[5] 우측 그림에서 첫 번째 커밋 후 그 뒤에 Update 문으로 데이터를 갱신하고 Delete 문으로 데이터를 삭제한 후 Insert 문을 사용해 데이터를 삽입한다. 만약 이 모든 과정이 오류 없이 수행되었다면 지금까지 실행한 모든 작업을 데이터베이스에 영구 저장하라는 명령으로 커밋을 수행한다.[10]
롤백[편집]
롤백(rollback) 연산은 작업 중 문제가 발생하여 트랜잭션의 처리과정에서 발생한 변경사항을 취소하는 명령어이다. 이 트랜잭션의 일부가 정상적으로 처리되더라도 트랜잭션의 원자성을 구현하기 위해 이 트랜잭션이 행한 모든 연산을 취소한다는 특징이 있다. 트랜잭션이 시작되기 이전의 상태로 되돌린다. 즉, 마지막 커밋을 완료한 시점으로 다시 돌아간다. 커밋하여 저장한 것만 복구한다. 롤백 시에는 해당 트랜잭션을 재시작하거나 폐기한다.[5] 우측 그림에서 롤백 명령은 마지막으로 수행한 커밋 명령까지만 정상 처리된 상태로 유지한다. 그 이후에 수행했던 모든 DML 명령어 작업들을 취소시켜 이전 상태로 원상 복귀 시킨다. 트랜잭션은 이렇듯 all or nothing(모든 것을 수행하던지 아무것도 하지 말던지) 방식으로 DML 명령어들을 처리한다.[10]
세이브포인트[편집]
세이브포인트(save point)는 '임시저장' 또는 '부분저장'과 같은 맥락으로 이해할 수 있다. 보통 롤백을 명시하면 삽입, 삭제, 업데이트 등의 작업 전체가 취소되는데, 세이브포인트는 전체가 아닌 특정 부분에서 트랜잭션을 취소하기 위해 사용한다. 세이브포인트를 쓰면 현재의 트랜잭션을 작게 분할하는 것이 가능하다. 세이브포인트는 여러 개의 에스큐엘(SQL)문의 실행을 수행하는 트랜잭션의 경우에 사용자가 트랜잭션 중간 단계에서 세이브포인트를 지정할 수 있다. 세이브포인트를 쓰려면 취소하려는 지점을 명시한 뒤, 그 지점까지 작업을 취소하는 식으로 사용하는데 이 지점을 세이브포인트라고 한다. 세이브포인트를 지정한 뒤 롤백 투 세이브포인트 이름;(rollback to save point name;)을 실행하면 해당 세이브포인트 지점까지 처리한 직업이 롤백된다.
스케줄 종류[편집]
직렬 스케줄[편집]
직렬 스케줄(Serial schedule)은 순서대로, 하나씩 트랜잭션을 실행하는 것으로 트랜잭션 하나의 실행이 완료되면 다른 트랜잭션을 시작하는 방식으로 하나씩 차례대로 실행하는 스케줄로서 트랜잭션이 실행되는 동안 다른 트랜잭션의 영향을 받을 수 없으므로 모순이 발생하지 않는다.[11]
직렬화 스케줄[편집]
직렬화 스케줄(Serializable schedule)은 병행 제어, 직렬 스케줄 장점을 가진 것으로 트랜잭션들이 동시에 자료 접근 연산들을 교차하며 실행시키면서도 결과가 직렬 스케줄과 동일한 스케줄이다. 즉, 병행 처리하지만 적절한 제어 조치를 취함으로써 일관성을 유지하는 스케줄로서 병행 제어에서 필요한 스케줄이다. 즉, 병행 제어 스케줄은 직렬성을 유지할 수 있다. 직렬성이란 트랜잭션들의 처리 결과가 직렬 처리와 동일한 효과를 가지는 스케줄 특성이다.[11]
병행처리[편집]
다수의 사용자가 데이터베이스에 요청을 보내게 되면 이러한 요청들을 처리할 방법이 필요하다. 만약 하나의 요청을 끝내고 다른 요청을 수행하는 방식이라면 처리시간이 매우 오래 걸린다. 그래서 병행처리 방식으로 처리를 한다. 트랜잭션을 병행처리하면 처리 효율이 높아지지만, 처리 과정에서 동일한 자료를 동시에 접근해서 오류가 생길 수 있다.
병행처리의 문제점 종류 내역 문제점 갱신 유실 문제 두 트랜잭션이 동시에 동일한 자료를 갱신 첫째 갱신이 유실 오류 읽기 문제 갱신하는 도중에 다른 트랜잭션이 읽기 낡은 자료 읽기 잘못된 요약 두 자료를 갱신하는 도중에 읽기 요약 결과 오류 무결성 제약조건 두 자료의 제약조건을 검사하지 않고 갱신 일관성 위반
따라서 병행제어가 필요한데, 병행제어가 필요한 이유는 다음과 같다.
- 분실된 업데이트 문제(The Lost Update Problem) : 두 개의 트랜잭션이 동일한 아이템에 접근하여 서로의 연산이 중첩될 때 결과적으로 올바르지 않은 값이 저장될 수 있다.
- 임시 업데이트 문제(The Temporary Update Problem) : 한 트랜잭션이 값을 업데이트하다가 중간에 트랜잭션이 실패하였다. 하지만 롤백하기 이전에 다른 트랜잭션이 값을 읽게 되면 올바르지 않은 값을 읽는 것이다.
- 잘못된 요약 문제(The Incorrect Summary Problem) : 한 트랜잭션이 aggregate 함수(Sum, Max, Min 등)를 실행하고 있는데, 다른 트랜잭션이 이 값들 중 하나를 업데이트하고 있을 때 aggregate 트랜잭션의 값이 업데이트되기 이전을 사용할 때이다.
데이터베이스 병행처리의 목적은 1) 트랜잭션의 충돌을 방지하기 위해 고립성을 강제하기 위함, 2) 데이터베이스의 일관성을 보존하기 위함, 3) read-write 또는 write-write 충돌을 막기 위함의 세 가지로서, 스케줄의 진정한 목적은 충돌 스케줄을 찾아 직렬화 스케줄을 만드는 것이다.[11]
록킹[편집]
트랜잭션이 자료를 배타적으로 접근할 수 있으면 그 트랜잭션이 완료된 후에 다른 트랜잭션이 실행되기 때문에 직렬성이 확보된다. 자료를 배타적으로 접근하는 방법이 바로 록킹 기법이다. 트랜잭션의 ACID 특성을 해치는 접근 연산은 주로 갱신이다. 읽기 연산은 자료 값을 바꾸지 않는다. 하지만 읽기 연산 도중에 갱신을 하게되면 일관성 유지가 어려울 수 있다. 트랜잭션에는 공유 록과 배타 록 2가지가 있다.
- 공유 록 : 특정 자료 Q에 공유 록을 걸면 다른 트랜잭션이 이 자료를 갱신할 수 없다. 공유 록(Shared Lock)이 걸린 Q는 다른 트랜잭션에 의해서 읽혀질 수 있다.[11]
- 배타 록 : 트랜잭션이 자료를 기록할 때 배타 록(Exclusive Lock) X를 걸어야 한다. 록 X를 가진 트랜잭션은 자료를 읽을 수도 있고, 갱신할 수도 있다. 배타 록 X가 걸린 자료는 공유 록 S를 가진 트랜잭션들에 의해서 읽혀질 수 없는데 더디리드(Dirty Read)를 방지하기 위해서이다.[11]
복제[편집]
복제 구성에서 있어서 슬레이브에서는 마스터에서 전송되어 온 업데이트성 쿼리를 실행하는 역할을 한다. 이 처리는 사실 업데이트성 쿼리를 실행하는 것만으로는 충분하지 않고 슬레이브는 마스터에서 보낸 업데이트성 쿼리 중에서 어디까지를 실행했는지라는 정보도 관리할 필요가 있다. 그렇게 처리하지 않으면 도중에 슬레이브가 멈추었을 경우 어디서부터 다시 시작하면 좋을지 알 수 없기 때문이다. 엄밀하게는 이 정보원들은 동일한 트랜잭션에서 원자성 있게 갱신해야 한다. 마이에스큐엘(MySQL)에서는 마스터가 트랜잭션이 커밋될 때마다 그 생신 에스큐엘(SQL) 문을 바이너리 로그에 기록할 때, 슬레이브에서는 바이너리 로그의 내용을 싫어하여 나가지만, 현재 어디까지 실행했는지를 관리하기 위해 실행을 마친 바이너리 로그의 위치 정보를 관리하는 InnoDB 테이블을 제공한다. 그리고 갱신 에스큐엘 문의 실행과 위치 정보 갱신을 동일한 트랜잭션에서 실시한다. 애플리케이션의 관점에서 모든 업데이트성 쿼리가 UPDATE 문 한 번밖에 없는 자동 커밋 쿼리라 할지라도 복제 구성과 조합한 시점에서 업데이트성 쿼리의 실행에 더하여 복제 상태 업데이트 처리도 모두 한 개의 트랜잭션으로 하지 않으면 안된다. 이것들이 하나의 트랜잭션으로 되어 있으면 어느 타이밍에 크래쉬해도 갱신 확정된 쿼리를 또다시 복제하거나, 반대로 복제를 날려 버리는 일은 없게 될 것이다.
블록체인[편집]
블록체인은 트랜잭션을 블록(Block) 단위의 체인(Chain) 형태로 저장하는 기술이다. 블록체인 상 저장 데이터는 트랜잭션 단위로 생성되게 된다. 트랜잭션은 일반적으로 이전 트랜잭션 출력을 새 트랜잭션 입력으로 참조하고 모든 입력 비트코인(Bitcoin) 값을 새 출력으로 바치는 구조이다. 또한, 트랜잭션은 이중 입력 부기 장부의 연결과 같다. 소유자 디지털 서명을 사용하여 값을 소비하는 비트코인의 각 금액에 대한 소유권 증명이 포함되어 있으며, 이는 누구든지 독립적으로 확인할 수 있다. 블록은 트랜잭션의 집합을 블록 단위로 기록하며 채굴 행위를 통해 약 10분(상황에 따라 다름)을 주기로 발행된다. 즉, 블록은 이전 블록의 해시 값(ID)를 포함한다. 블록은 일종의 데이터 패킷으로 위 그림과 같이 몇 가지 정보들을 담고 있다. 가장 중요한 것으로 참여자들이 화폐를 거래한 거래내역, 그리고 이전 블록의 해시 값, 채굴 난이도, 논스(Nonce) 등이 포함된다. 매 블록은 바로 전 블록의 해시값을 담고 있으며, 이렇게 이어진 블록들은 시간순으로 발생한 이체 내역들을 담고 있는 하나의블록체인을 이룬다.[12]
각주[편집]
- ↑ 1.0 1.1 1.2 1.3 1.4 1.5 1.6 victolee, 〈(DB이론) 트랜잭션(transaction)과 ACID 특성을 보장하는 방법〉, 《티스토리》, 2018-02-09
- ↑ 데이터베이스 트랜잭션 위키백과 - https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98
- ↑ 〈BEGIN TRANSACTION(Transact-SQL)〉, 《마이크로소프트》, 2016-06-10
- ↑ 〈COMMIT TRANSACTION(Transact-SQL)〉, 2016-09-09
- ↑ 5.0 5.1 5.2 5.3 5.4 5.5 코딩팩토리, 〈(DB기초) 트랜잭션이란 무엇인가?〉, 《티스토리》, 2018-08-20
- ↑ 6.0 6.1 Mommoo, 〈트랜잭션(Transaction)이란?〉, 《티스토리》, 2017-02-27
- ↑ 7.0 7.1 7.2 7.3 Lim-Ky, 〈(DataBase) 트랜잭션이란? (Transaction)〉, 《티스토리》, 2017-10-06
- ↑ 8.0 8.1 8.2 8.3 망나니 개발자, 〈(Database) 8. 트랜잭션, 동시성 제어, 회복〉, 《티스토리》, 2017-12-12
- ↑ 9.0 9.1 9.2 kmmguumnn, 〈트랜잭션(Transaction)이란?〉, 《티스토리》, 2019-03-03
- ↑ 10.0 10.1 10.2 쩨리쩨리, 〈(SQL) Transaction(트랜잭션)〉, 《티스토리》, 2018-04-24
- ↑ 11.0 11.1 11.2 11.3 11.4 jhkang-dev, 〈(데이터베이스) 트랜잭션〉, 《티스토리》, 2018-11-28
- ↑ kimjunyong, 〈블록체인의 정의와 기술 비전공자도 이해하는 기본적 이해〉, 《미디움》, 2018-11-13
참고자료[편집]
- 데이터베이스 트랜잭션 위키백과 - https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98
- 마이크로소프트 BEGIN TRANSACTION(Transact-SQL) - https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/begin-transaction-transact-sql?view=sql-server-ver15
- 마이크로소프트 COMMIT TRANSACTION(Transact-SQL) - https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/commit-transaction-transact-sql?view=sql-server-ver15
- 코딩팩토리, 〈(DB기초) 트랜잭션이란 무엇인가?〉, 《티스토리》, 2018-08-20
- Mommoo, 〈트랜잭션(Transaction)이란?〉, 《티스토리》, 2017-02-27
- victolee, 〈(DB이론) 트랜잭션(transaction)과 ACID 특성을 보장하는 방법〉, 《티스토리》, 2018-02-09
- Lim-Ky, 〈(DataBase) 트랜잭션이란? (Transaction)〉, 《티스토리》, 2017-12-12
- 망나니 개발자, 〈(Database) 8. 트랜잭션, 동시성 제어, 회복〉, 《티스토리》, 2017-10-06
- kmmguumnn, 〈트랜잭션(Transaction)이란?〉, 《티스토리》, 2019-03-03
- 쩨리쩨리, 〈(SQL) Transaction(트랜잭션)〉, 《티스토리》, 2018-04-24
- jhkang-dev, 〈(데이터베이스) 트랜잭션》, 2018-11-28
- kimjunyong, 〈블록체인의 정의와 기술 비전공자도 이해하는 기본적 이해〉, 《미디움》, 2018-11-13
같이 보기[편집]