-- MyISAM 을 사용하는 테이블 생성
CREATE TABLE tab_myisam (fdpk INT NOT NULL , PRIMARY KEY (fdpk)) ENGINE = MyISAM;
-- 프라이머리키 컬럼 fdpk에 데이터 insert
INSERT INTO tab_myisam (fdpk) values (3);
-- INNODB 를 사용하는 테이블 생성
CREATE TABLE tab_innodb (fdpk INT NOT NULL , PRIMARY KEY (fdpk)) ENGINE = INNODB;
-- 프라이머리키 컬럼 fdpk에 데이터 insert
INSERT INTO tab_innodb (fdpk) values (3);
-- AUTO-COMMIT 모드 활성
SET autocommit =ON;
-- fdpk에 데이터 1, 2, 3 insert
INSERT INTO tab_myisam (fdpk) values (1), (2), (3);
INSERT INTO tab_innodb (fdpk) values (1), (2), (3);
insert 문 실행하면 프라이머리키 중복 오류 발생
결과 확인 \
MyISAM 테이블에는 오류가 발생했음에도 '1'과 '2'는 INSERT 된 상태로 남아 있다.
로그에서도 롤백될 수 없음을 알려준다.
Some non-transactional changed tables couldn't be rolled back
InnoDB는 쿼리 중 일부라도 오류가 발생하면 전체를 원 상태로 만든다는 트랜잭션의 원칙대로 INSERT 문장을 실행하기 전 상태로 그대로 복구했다.
MyISAM 테이블에서 발생하는 이러한 현상을 부분 업데이트(Partial Update)라고 표현하며, 이러한 부분 업데이트 현상은 테이블 데이터의 정합성을 맞추는데 상당히 어려운 문제를 만들어 낸다.
예시로 살펴보자.
서비스 기능중 '사용자 게시물 등록' 이 있다.
왼쪽은 이 기능에 연관된 모든 로직이 하나의 트랜잭션안에 있는 경우다.
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미치지만,
스토리지 엔진 레벨의 잠금은 스토리지 엔진 간 상호 영양을 미치지는 않는다.
-- 명시적 테이블 락 획득
LOCK TABLES [READ | WRITE]
-- 명시적 테이블 락 반납
UNLOCK TABLES
https://gywn.net/2013/12/mysql-user-level-lock/
실습 쿼리
-- 트랜잭션 비교 예
CREATE TABLE tab_myisam (fdpk INT NOT NULL , PRIMARY KEY (fdpk)) ENGINE = MyISAM;
INSERT INTO tab_myisam (fdpk) values (3);
CREATE TABLE tab_innodb (fdpk INT NOT NULL , PRIMARY KEY (fdpk)) ENGINE = INNODB;
INSERT INTO tab_innodb (fdpk) values (3);
SET autocommit =ON;
INSERT INTO tab_myisam (fdpk) values (1), (2), (3);
INSERT INTO tab_innodb (fdpk) values (1), (2), (3);
-- table lock 예시
-- 1. 테이블 생성
CREATE TABLE messages (
id INT NOT NULL AUTO_INCREMENT,
message VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
-- 2. 현재 세션 조회
SELECT CONNECTION_ID();
-- 3. insert a row
INSERT INTO messages(message)
VALUES('Hello');
-- 4. row 확인
SELECT * FROM messages;
-- 5. READ lock 걸기
LOCK TABLES messages READ;
-- 6. lock을 건 세션에서 insert 시도
INSERT INTO messages(message)
VALUES('Hi');
-- 9. 프로세스 확인
SHOW PROCESSLIST;
-- 10. unlock
UNLOCK TABLES;
-- 11. 결과 확인
-- 네임드락 예시
create table t_sessions(
user_id int not null,
s_key varchar(32) not null,
create_at datetime not null,
primary key(user_id, create_at),
key ix_skey(s_key)
) engine=innodb
partition by range columns(create_at)(
partition p_201310 values less than ('2022-12-26'),
partition p_201311 values less than ('2022-12-27')
)
;
select get_lock('session key', 1);
select 1 from t_sessions
where s_key = 'session key'
;
insert into t_sessions values (1,'session key',now())
;