트랜잭션이란
예시 코드
// MyISAM 스토리지 엔진 기반 테이블
CREATE TABLE tab_myisam (fdpk int not null, primary key(fdpk) ENGINE=MyISAM;
INSERT INTO tab_myisam (fdpk) VALUES (3);
// InnoDB 스토리지 엔진 기반 테이블
CREATE TABLE tab_innodb (fdpk int not null, primary key(fdpk) ENGINE=InnoDB;
INSERT INTO tab_innodb (fdkp) VALUES (3);
SET autocommit=ON;
// MyISAM 스토리지 엔진 사용 테이블 INSERT
INSERT INTO tab_myisam (fdpk) VALUES (1),(2),(3);
// InnoDB 스토리지 엔진 사용 테이블 INSERT
INSERT INTO tab_innodb (fdpk) VALUES (1),(2),(3);
결과
주의 사항
MySQL의 잠금은 크게 스토리지 엔진 레벨, MySQL 엔진 레벨로 나눌 수 있음
MySQL 엔진은 스토리지 엔진을 제외한 나머지 부분
MySQL 엔진의 잠금은 모든 스토리지 엔진에 영향을 미치지만 스토리지 엔진의 잠금은 스토리지 엔진 간 영향을 받지 않음
MySQL 엔진은 테이블 데이터 동기화를 위한 테이블 락 이외에 테이블의 구조를 잠그는 메타데이터 락, 사용자 필요에 맞게 사용할 수 있는 네임드 락 잠금 기능도 제공
글로벌 락
FLUSH TABLES WITH READ LOCK;
명령으로 획득 가능테이블 락
LOCK TABLES table_name [ READ | WRITE ];
명령으로 특정 테이블 락 획득 가능UNLOCK TABLES;
명령으로 잠금을 반납네임드 락
GET_LOCK() 함수를 이용해 임의의 문자열에 대해 잠금을 설정할 수 있음
이 잠금의 특징은 대상이 테이블, 레코드, AUTO_INCREMENT와 같은 데이터베이스 객체가 아니라는 점이다
네임드 락은 단순히 사용자가 지정한 문자열에 대해 획득하고 반납하는 잠금
데이터베이스 서버 1대에 5대의 웹 서버가 접속해서 서비스하는 상황에서 5대의 웹 서버가 어떤 정보를 동기화해야 하는 요건처럼 여러 클라이언트가 상호 동기화를 처리해야 할 때 사용함(많이 사용되는 기능 아님)
// "mylock"이라는 문자열에 대해 잠금을 획득
// 이미 잠금을 사용하면 2초동안 대기(2초 이후 자동으로 잠금 해제)
SELECT GET_LOCK('mylock', 2);
// "mylock"이라는 문자열에 대해 잠금이 설정돼 있는지 확인
SELECT IS_FREE_LOCK('mylock');
// "mylock"이라는 문자열에 대해 획득했던 잠금을 반납
SELECT RELEASE_LOCK('mylock');
// 3개 함수 모두 정상적으로 락을 획득하거나 해제한 경우에는 1을
// 아니면 NULL 또는 0을 반환
메타데이터 락
데이터베이스 객체(테이블, 뷰 등)의 이름이나 구조를 변경하는 경우에 획득하는 잠금
메타데이터 락은 명식적으로 획득/해제할 수 있는 것이 아니며, 테이블 이름을 변경하는 경우 자동으로 획득하는 잠금4
RENAME TABLE
명령을 실행하는 경우 원래 이름과 변경될 이름 두 개 모두 한꺼번에 잠금을 설정
실시간으로 테이블을 바꿔야 하는 요건이 배치 프로그램에서 자주 발생하는데, 이에 메타데이터 락이 발생
// 배치 프로그램에서 별도의 임시 테이블(rank_new)에 서비스용 랭킹 데이터를 생성
// 랭킹 배치가 완료되면 현재 서비스용 랭킹 테이블(rank)을 rank_backup으로 백업
// 새로 만들어진 랭킹 테이블(rank_new)을 서비스용으로 대체하고자 하는 경우
RENAME TABLE rank TO rank_backup, rank_new TO rank;
RENAME TABLE rank TO rank_backup;
RENAME TABLE rank_new TO rank;
때로는 메타데이터 잠금과 InnoDB의 트랜잭션을 동시에 사용해야 하는 경우도 존재
CREATE TABLE access_log (
id BIGINT NOT NULL AUTO_INCREMENT,
client_id INT UNSIGNED,
access_dttm TIMESTAMP,
...,
PRIMARY KEY(id)
);
어느날 위 테이블 구조를