2009년 4월 15일 수요일

InnoDB - 트랜잭션4

○4개의 트랜잭션 분리레벨

여러개의 클라이언트가 동시에 같은 테이블에  대해서 트랜잭션처리를 실행하는 경우는 데이터의 조회, 저장의 동작이 문제가 되곤 한다. 
이것을 ANSI/ISO SQL규격에서 규정한 것이 「트랜잭션 분리레벨」이다. 

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE
InnoDB는 이 4개의 트랜잭션 분리레벨을 전부 지원하고 있다. 
그러나 NDB하고 BDB는 READ COMMITTED만을 지원하고 있다. 

MySQL에서는 SQL문에서 사용하는 트랜잭션 분리레벨을 지정가능하다. 
이 4개의 트랜잭션 분리레벨에 대한 데이터의 조회방법의 차이는 다음과 같다. 

 dirty readnon repeatable readphantom read
READ UNCOMMITTEDooo
READ COMMITTEDxoo
REPEATABLE READxxo
SERIALIZABLExxx

o:발생을 허가, x:발생하지 않음

1. dirty read
여러 개의 클라이언트가 동시에 테이블에 접속해 있다고 하자. 
이 때 한쪽에서 아직 COMMIT하고 있는 데이터를 다른 한쪽에서 조회가 가능한 상황이 dirty read이다. 

2. non-repeatable read (반복불능 조회)
여러 개의 클라리언트가 동시에 테이블에 접속해 있다고 하자. 
한쪽(A)이 어떤 레코드를 SELECT하고 다른 한쪽(B)가 A가 SELECT한 레코드를 갱신하고 COMMIT한다. 
여기에서 다시 A가 같은 레코드를 SELECT했을 때  값이 B가 변경한 것으로 변해 있는 상황이 non repeatable read이다. 
다시 말하면 지난번 조회내용과 이번 조회내용이 다르다는 것이다. 

3. phantom read
non-repeatable read가 UPDATE에 관한 사항이었던 것에 비해 phantom read는 INSERT에 관한 사항이다. 
한쪽(A)이 어떤 레코드를 SELECT한 후 다른 한쪽(B)가 새로운 레코드를 INSERT하고 COMMIT한다고 하자.  여기에서 다시 A가 같은 조건으로 레코드를 조회할 경우 B가 추가한 새로운 레코드도 조회되는 상황이 phantom read이다. 
지난번 조회내용과 이번 조회내용이 다르다.


InnoDB에서는 REPEATABLE READ대해서 phantom read는 발생하지 않는다. 
또 InnoDB의 SERIALIZABLE는 lock방법을 명시하지 않은 모든 SELECT문을 
SELECT ... LOCK IN SHARE MODE로서 취급한다. 






InnoDB - 트랜잭션3

○auto commit모드를 무효로 하기
auto commit모드를 무효로 하기 위해서는 다음과 같이 조작한다. 

auto commit모드를 무효화하기
mysql> SET AUTOCOMMIT=0;

auto commit모드를 무효화하면 START TRANSACTION의 실행을 잊어버렸어도 자동으로 트랜잭션이 시작된다. 또  COMMIT, ROLLBACK을 실행하면 그 다음 트랜잭션이 자동적으로 개시된다. 

또 다른 auto commit모드를 무효화하는 방법에는 다음처럼 init-connect옵션을 지정하는 방법도 있다. 

init-connect옵션으로 auto commit모드를 무효화하기 
shell$ mysqld --init-connect='SET AUTOCOMMIT=0'

이것은 클라이언트가 서버에 접속할 때마다 최초에 자동적으로 SET AUTOCOMMI=0를 실행하는 옵션이다.  다만 이 기능은 SUPPER권한이 있는 유저로 접속해온 클라이언트에 대해서는 기능하지 않으므로 주의해야 한다. 





2009년 4월 11일 토요일

InnoDB - 트랜잭션2

◎트랜잭션이 무효인 SQL문

MySQL에서는 모든 SQL문이 트랜잭션 대상이 되지는 않는다. 
다음과 같은 SQL문이 실행되었을 때  만약 트랜잭션모드이었다고 하더라도 자동적으로  commit되어버린다.  주의 해야한다!

  • ALTER FUNCTION  ※묵시적 commit은 5.0.13부터..
  • ALTER PROCEDURE ※묵시적 commit은 5.0.13부터..
  • ALTER TABLE
  • BEGIN
  • CREATE DATABASE  ※묵시적 commit은 5.0.8부터..
  • CREATE FUNCTION  ※묵시적 commit은 5.0.13부터..
  • CREATE INDEX
  • CREATE PROCEDURE  ※묵시적 commit은 5.0.13부터..
  • CREATE TABLE      ※묵시적 commit은 5.0.8부터..
  • DROP DATABASE  ※묵시적 commit은 5.0.8부터..
  • DROP FUNCTION  ※묵시적 commit은 5.0.13부터..
  • DROP INDEX
  • DROP PROCEDURE  ※묵시적 commit은 5.0.13부터..
  • DROP TABLE
  • LOAD MASTER DATA
  • LOCK TABLES
  • LOAD DATA INFILE
  • RENAME TABLE
  • SET AUTOCOMMIT=1
  • START TRANSACTION
  • TRUNCATE TABLE  ※묵시적 commit은 5.0.8부터..
  • UNLOCK TABLES

◎스냅샷의 타이밍 
보통 InnoDB의 REPEATABLE READ에서는 SELECT한 시점의 데이터가 스탭샷용으로 보존된다.  그러나 START TRANSACTION WITH CONSISTENT SNAPSHOT의 경우에는 이 문장을 실행한 때의 데이터를 스냅샷용으로 보존한다.


InnoDB - 트랜잭션1

MySQL에서는 모든 스토리지 엔진이 트랜잭션기능을 지원하는 것은 아니다. 

트랜잭션을 지원하는 스토리지 엔진은 InnoDB하고 NDB, BDB이다. 

또  MySQL에는 auto commit 모드라는 개념이 있다. 
auto commit이 유효(MySQL의 표준)인 경우 트랜잭션개시에는 반드시 START TRANSACTION이나 BEGIN이 필요하다. 

이것을 잊어버리면 각 문장을 트랜잭션 처리가 되지 않고 실행할 때 곧바로 Commit되어 버린다. 

덧붙여 BEGIN은 Stored Preocedure에서도 사용하는 키워드이기도 하기 때문에 
이글에서 트랜잭션에 관해서는 START TRANSACTION을 사용하는 것으로 한다. 

START TRANSACTION예
mysql>START TRANSACTION
mysql>UPDATE t SET a=a+1 WHERE a<100;
mysql>INSERT t(a) values(200);
mysql>ROLLBACK;

MySQL에서는 트랜잭션중에  또다시 트랜잭션을 작성하는 것은 불가능하다. 
또 트랜잭션 도중에 COMMIT/ROLLBACK을 잊어버리고 다시 START TRANSACTION을 실행했을 때,  지금까지의 트랜잭션데이터는 데이터에 반영되어 버리기 때문에 주의 해야한다.