본문 바로가기

DBMS/MySQL & MariaDB

MySQL 저장 엔진과 트랜잭션 처리 (2)


이제 트랜잭션에 대해 알아보도록 하겠습니다.


2. 트랜잭션(Transaction)


  정의

트랜잭션이란 하나 이상의 SQL문으로 이루어진 작업의 단위입니다.  따라서 트랜잭션의 모든 과정은 전부 완료되거나, 

혹은 취소되거나 둘 중 하나여야합니다. 


계좌이체를 하는 과정을 생각해봅시다. 계좌이체를 하려면 어떻게 해야할까요? 


우선 ATM기에 카드를 넣겠죠. 순차적으로 비밀번호와 인출할 금액을 입력하면 ATM기는 돈을 지급 할 것입니다. 

하지만 이러한 과정에 있어서 기계가 고장나게되면 어떻게 될까요? 전산상으로는 돈이 인출이 되었는데, 

실제로는 인출이 안되었다거나 혹은 인출은 되었는데 전산상으로는 돈이 인출되지 않았다거나.. 


이런 일이 정말 발생하게 된다면 상당히 심각한 문제가 발생되겠죠.  

따라서 이러한 일이 미연에 방지되도록 저희는 코딩을 해야합니다.  그 방법이 트랜잭션입니다. 


전산상으로도 처리가 잘되고 돈도 인출이 잘되고 이 과정을 한 묶음으로 처리하여 작업의 완전성을 보장해주는 것이죠.



  특성


트랜잭션은 다음 4가지 특성으로 정의되며, ACID 특성이라고 합니다.


Atomicity : 원자성. all or nothing, 모든 작업은 모두 완료 되거나 취소되어야 한다.

Consistency : 일관성. 트랜잭션이 성공적으로 처리되면 데이터는 일관성있게 데이터베이스에 반영되어야 한다.

Isolation : 독립성, 분리성. 여러 트랜잭션이 실행되더라도 각각의 트랜잭션은 서로 간섭해서는 안된다.

Durability : 지속성, 영속성. 수행된 트랜잭션은 어떤 장애가 발생되더라도 보존되어야 한다.



  격리 수준

트랜잭션을 원하는 의도대로 사용하려면 격리 수준(Isolation Level)에 대해 명확하게 알고 넘어가야 합니다. 

격리 수준이란 트랜잭션에서 일관성이 없는 데이터를 허용 하는 정도 입니다.  무조건적으로 트랜잭션 간의 관여를 막는것은 

데이터베이스의 성능을 저하시킬뿐만 아니라 사용자의 의도대로 사용 할 수 없어지기 때문입니다.  따라서 격리 수준을 조금 완화해

서로 영향을 받으면서 상충되지 않게 적절한 레벨을 지정하여 처리 하도록 해주어야 합니다. 


// 격리 수준 확인
SHOW VARIABLES LIKE '%isolation%';

(1) Read Uncommitted (level 0)

커밋되지 않은 읽기, 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용.
A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 B라는 커밋 되지않은 데이터 B를 읽을 수 있다.
Dirty Read, Non-Repeatable Read, Phantom Read가 발생할 확률이 높다.

(2) Read committed (level 1)

커밋된 읽기, 커밋되어 확정된 데이터를 다른 트랜잭션에서 읽는 것을 허용.
A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 해당 데이터에 접근할 수 없다.
Non-Repeatable Read, Phantom Read가 발생할 확률이 높다.

(3) Repeatable Read (level 2)

: 반복 읽기, 트랜잭션 내에서 한번 조회한 데이터가 반복적으로 조회 된다.  
A 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 B 트랜잭션이 갱신하거나 삭제하는 것을 허용하지 않음으로써 
같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴 한다.
Phantom Read가 발생할 확률이 높다.

(4) Serializable (level 3)

: 직렬화 가능, 
트랜잭션이 완료될 때까지 SELECT 문장에 사용하는 모든 데이터는 shared lock이 걸리므로 다른 사용자는 그 영역에 해당되는 
데이터에 대한 수정 및 입력이 불가능 하다.
Dirty Read, Non-Repeatable Read, Phantom Read가 발생할 확률이 낮지만 동시 처리 성능은 크게 떨어질 수 있다.

Dirty Read
커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽게 되는 경우를 말한다.
Repeatable Read 
어떤 트랜잭션 내에서 같은 쿼리를 여러번 수행할 때 해당 행을 변경해도 항상 같은 데이터만 읽어 드리는 경우를 말한다.
Phantom Read
한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽을 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 
나타나는 현상. 이는 트랜잭션 도중 새로운 레코드가 삽입되는 것을 허용하기 때문에 나타난다. 



  Commit 과 Rollback


변경된 값을 테이블에 쓰기 위해서는 commit 이라는 명령어를 사용하고, 원래의 상태로 되돌리기 위해서는 Rollback 이란 명령어를 사용합니다. 


  InnoDB 엔진에서의 트랜잭션


InnoDB의 기본 격리 수준(Isolation Level)은 REPEATABLE-READ 이므로 바로 트랜잭션 쿼리문을 날리게 되면 아무런 변경 사항없이 
똑같은 데이터만 반복 조회 될 것입니다. 당연하게도 트랜잭션을 사용하기 위해서는 격리 수준의 값을 변경해주어야 합니다. 

// 격리 수준 변경
SET tx_isolation = "변경할 isolation 레벨";  
COMMIT;


만약, 격리 수준을 변경을 하고나서도 트랜잭션 처리가 정상적으로 되지 않는다면 autocommit 값이 true인지 확인해보아야합니다.
이 옵션은 변경 할 데이터의 내용을 테이블에 바로 반영하지 않게 하기 위해 쓰이는 옵션입니다. 이 값을 0 (false) 값으로 설정하면 
commit 명령을 내리기 전까지 변경 사항은 반영되지 않습니다.
// autocommit 확인
SELECT @@ autocommit;
// autocommit 변경 
SET autocommit = 0;

note

MyISAM 과 같은 트랜잭션을 지원하지 않는 엔진의 경우 Rolback , Commit 값이 무의미 합니다. 따라서 autocommit의 값과 상관없이 autocommit이 일어난다고 생각 하시면 됩니다. 


'DBMS > MySQL & MariaDB' 카테고리의 다른 글

MySQL 백업 및 복원  (0) 2020.02.18
MySQL 기본 명령어  (0) 2019.03.05
MySQL 저장 엔진과 트랜잭션 처리 (1)  (0) 2017.11.02