반응형
들어가며
Transaction Read
- Dirty Read
- 다른 트랜잭션에서 아직 COMMIT하지 않은 신뢰할 수 없는 데이터를 읽을 수 있는 현상
- Non-repeatable Read
- 한 트랜잭션에서 동일한 SELECT 쿼리의 결과가 다르게 나타날 수 있는 현상
- Phantom Read
- 이전의 SELECT 쿼리의 결과에 없던 row가 생기는 현상
Isolation Level 종류
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
현재 Isolation Level 확인하기
mysql> SHOW VARIABLES WHERE VARIABLE_NAME='tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
READ UNCOMMITTED
설명
- 다른 트랜잭션에서 아직 COMMIT하지 않은 신뢰할 수 없는 데이터를 조회할 수 있는 level
- Dirty Read, Non-repeatable Read, Phantom Read 현상 전체가 발생할 수 있음
예제
- session-1
mysql> SET SESSION transaction isolation level READ UNCOMMITTED; mysql> START TRANSACTION; mysql> SELECT * FROM user; +----+-------+ | id | name | +----+-------+ | 1 | user1 | | 2 | user2 | | 3 | user3 | +----+-------+
- session-2
mysql> START TRANSACTION; mysql> UPDATE user SET name = 'updated' WHERE id = 1; mysql> INSERT INTO user (name) VALUES ('inserted');
- session-1
mysql> SELECT * FROM user; +----+----------+ | id | name | +----+----------+ | 1 | updated | | 2 | user2 | | 3 | user3 | | 5 | inserted | +----+----------+
READ COMMITTED
설명
- 다른 트랜잭션에서 COMMIT된 데이터만 읽을 수 있는 level
- Dirty Read 현상 방지, Non-repeatable Read, Phantom Read 현상은 재현됨
예제
- session-1
mysql> SET SESSION transaction isolation level READ COMMITTED; mysql> START TRANSACTION; mysql> SELECT * FROM user; +----+-------+ | id | name | +----+-------+ | 1 | user1 | | 2 | user2 | | 3 | user3 | +----+-------+
- session-2
mysql> START TRANSACTION; mysql> UPDATE user SET name = 'updated' WHERE id = 1; mysql> INSERT INTO user (name) VALUES ('inserted');
- session-1
mysql> SELECT * FROM user; +----+-------+ | id | name | +----+-------+ | 1 | user1 | | 2 | user2 | | 3 | user3 | +----+-------+
- session-2
mysql> COMMIT;
- session-1
mysql> SELECT * FROM user; +----+----------+ | id | name | +----+----------+ | 1 | updated | | 2 | user2 | | 3 | user3 | | 6 | inserted | +----+----------+
REPEATABLE READ
설명
- MySQL 기본 isolation level
- 동시성과 안정성의 균형을 가장 잘 맞춘 level
- Dirty Read, Non-repeatable Read, Phantom Read 현상 모두 방지
예제
- session-1
mysql> SET SESSION transaction isolation level REPEATABLE READ; mysql> START TRANSACTION; mysql> SELECT * FROM user; +----+-------+ | id | name | +----+-------+ | 1 | user1 | | 2 | user2 | | 3 | user3 | +----+-------+
- session-2
mysql> START TRANSACTION; mysql> UPDATE user SET name = 'updated' WHERE id = 1; mysql> INSERT INTO user (name) VALUES ('inserted');
- session-1
mysql> SELECT * FROM user; +----+-------+ | id | name | +----+-------+ | 1 | user1 | | 2 | user2 | | 3 | user3 | +----+-------+
- session-2
mysql> COMMIT;
- session-1
mysql> SELECT * FROM user; +----+-------+ | id | name | +----+-------+ | 1 | user1 | | 2 | user2 | | 3 | user3 | +----+-------+
SERIALIZABLE
설명
- REPEATABLE READ와 동일하지만 shared lock(read lock)을 걸어 다른 트랜잭션에서 읽기는 되지만 쓰기 작업은 block되는 특징을 갖음
- 동시성을 상당 부분 포기하고 안정성에 큰 비중을 두는 level
예제 - 같은 ROW 데이터를 수정하려 할 경우
- session-1
mysql> SET SESSION transaction isolation level SERIALIZABLE; mysql> START TRANSACTION; mysql> SELECT * FROM user WHERE id = 1; +----+-------+ | id | name | +----+-------+ | 1 | user1 | +----+-------+
mysql> UPDATE user SET name = 'user1-a' WHERE id = 1; mysql> SELECT * FROM user WHERE id = 1; +----+---------+ | id | name | +----+---------+ | 1 | user1-a | +----+---------+
- session-2
mysql> START TRANSACTION; mysql> SELECT * FROM user WHERE id = 1; +----+-------+ | id | name | +----+-------+ | 1 | user1 | +----+-------+
mysql> UPDATE user SET name = 'user1-b' WHERE id = 1; // block됨
- session-1
mysql> COMMIT; mysql> SELECT * FROM user WHERE id = 1; +----+---------+ | id | name | +----+---------+ | 1 | user1-a | +----+---------+
- session-2
mysql> COMMIT; mysql> SELECT * FROM user WHERE id = 1; +----+---------+ | id | name | +----+---------+ | 1 | user1-b | +----+---------+
예제 - 다른 ROW 데이터를 수정하려 할 경우
- session-1
mysql> SET SESSION transaction isolation level SERIALIZABLE; mysql> START TRANSACTION; mysql> SELECT * FROM user WHERE id = 1; +----+-------+ | id | name | +----+-------+ | 1 | user1 | +----+-------+
mysql> UPDATE user SET name = 'user1-a' WHERE id = 1; mysql> SELECT * FROM user WHERE id = 1; +----+---------+ | id | name | +----+---------+ | 1 | user1-a | +----+---------+
- session-2
mysql> START TRANSACTION; mysql> SELECT * FROM user WHERE id = 2; +----+-------+ | id | name | +----+-------+ | 2 | user2 | +----+-------+
mysql> UPDATE user SET name = 'user2-b' WHERE id = 2; // block되지 않음 mysql> SELECT * FROM user WHERE id = 2; +----+---------+ | id | name | +----+---------+ | 2 | user2-b | +----+---------+
- session-1
mysql> COMMIT; mysql> SELECT * FROM user; +----+---------+ | id | name | +----+---------+ | 1 | user1-a | | 2 | user2 | | 3 | user3 | +----+---------+
- session-2
mysql> COMMIT; mysql> SELECT * FROM user; +----+---------+ | id | name | +----+---------+ | 1 | user1-a | | 2 | user2-b | | 3 | user3 | +----+---------+
Transaction, Lock 관련 테이블 조회
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM information_schema.innodb_lock_waits;
SELECT * FROM information_schema.innodb_trx;
참고
반응형
'Development > MySQL' 카테고리의 다른 글
[MySQL] JOIN (0) | 2021.02.25 |
---|---|
[MySQL] Storage Engine (0) | 2020.12.29 |
[MySQL] 쿼리 (0) | 2020.12.29 |
[MySQL] 설치하기 (0) | 2019.09.29 |
[Database] 옵티마이저 (0) | 2018.07.15 |