Transaction Isolation Level
์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐ ์ค ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋์ ํ๋ฉด ๊ฒฉ๋ฆฌ ์์ค์ ๋ํ ์ดํด๊ฐ ์์ฐ์ค๋ฝ๊ฒ ์๊ตฌ๋ฉ๋๋ค. ๊ฒฉ๋ฆฌ ์์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ACID ์ฑ์ง ์ค Isolation ์ ํด๋นํ๋ฉฐ, ์ฌ๋ฌ ํธ๋์ญ์ ์ด ๋์์ ๋ณ๊ฒฝ์ ์ํํ ๋ ์ฑ๋ฅ๊ณผ ์์ ์ฑ, ์ผ๊ด์ฑ ๋ฐ ์ฌํ์ฑ ๊ฐ์ ๊ทํ์ ๋ฏธ์ธํ๊ฒ ์กฐ์ ํ๋ ์ค์ ์ ๋๋ค. SQL:1992 ํ์ค์์ ์ ๊ณตํ๋ 4๊ฐ์ง ๊ฒฉ๋ฆฌ ์์ค์ ์ข ๋ฅ๋ ์๋์ ๊ฐ์ต๋๋ค.
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE
MySQL ์ InnoDB
๋ MVCC ์ 2-Phase Locking ์ ์ฅ์ ์ ์ ์ ํ ์กฐํฉํ์ฌ ํธ๋์ญ์
๋ชจ๋ธ์ ๊ตฌํํ์๋๋ฐ์. ์ด๋ฅผ ์ดํดํ๊ธฐ ์ํด์ InnoDB
์ Locking, Consistent Non-Locking Read, Locking Read ๋ฑ๊ณผ ๊ฐ์ ๊ฐ๋
์ด ์ ํ๋์ด์ผ ํฉ๋๋ค.
CREATE TABLE test (
id BIGINT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age BIGINT(20) NOT NULL,
PRIMARY KEY (id)
);
insert into test (id, name, age) values (1, 'quaritch', 25);
insert into test (id, name, age) values (2, 'orca', 26);
insert into test (id, name, age) values (3, 'chan', 26);
insert into test (id, name, age) values (6, 'ori', 27);
insert into test (id, name, age) values (10, 'awesomeo', 26);
์ด ๊ธ์์ ์ฌ๋ฌ ์์๋ค์ด ์ฌ์ฉ๋ ์์ ์ ๋๋ค. ๋ชจ๋ ์์๋ ์ ํ ์ด๋ธ์ ๋ฐํ์ผ๋ก ์งํ๋๋ ์ ์ ์ฐธ๊ณ ํ๋ฉฐ ์ฝ์ผ์๋ฉด ์ข ๋ ์ํํ ์ดํด๊ฐ ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ต๋๋ค.
InnoDB Locking
MySQL ์ InnoDB
์์ ๋ค์ํ Locking ๊ธฐ๋ฒ์ ์ฌ์ฉํฉ๋๋ค. ๊ทธ ์ค InnoDB
์ ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค์ ๊ตฌํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋ํ์ ์ธ 3๊ฐ์ง Lock ์ ๋ํด ์ฐ์ ์ดํด๋ณด๊ณ ์ ํฉ๋๋ค.
Record Lock
Record Lock
์ ์ธ๋ฑ์ค ๋ ์ฝ๋์ ์ค์ ๋๋ Lock ์
๋๋ค. ํ
์ด๋ธ์ ์ธ๋ฑ์ค๊ฐ ์ ์๋์ง ์์์ด๋ InnoDB
์์ ์จ๊ฒจ์ง Clustered Index ๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ํ์ฉํ์ฌ Record Lock
์ ์ ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, SELECT name FROM test WHERE id = 1 FOR UPDATE;
๋ผ๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ฉด id
๊ฐ 1 ์ ํด๋นํ๋ ๋ ์ฝ๋์ Record Lock
์ด ์ค์ ๋๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์
์ด id
๊ฐ 1 ์ธ ๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๋ ์์
์ ์ํํ ์ ์์ต๋๋ค.
์๋๋ ํด๋น ์ํฉ์ ์ฐ์ถํ๊ณ SHOW ENGINE INNODB STATUS
๋ฅผ ํตํด Record Lock
์ด ์ค์ ๋ ๊ฒ์ ํ์ธํ ๋ก๊ทธ์
๋๋ค.
RECORD LOCKS space id 10 page no 4 n bits 72 index PRIMARY of table `transaction_test`.`test`
trx id 3162 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 8; hex 8000000000000001; asc ;;
1: len 6; hex 000000000c4b; asc K;;
2: len 7; hex 820000008e0110; asc ;;
3: len 8; hex 7175617269746368; asc quaritch;;
4: len 8; hex 8000000000000019; asc ;;
Gap Lock
Gap Lock
์ ์ธ๋ฑ์ค ๋ ์ฝ๋ ๊ฐ์ Gap ํน์ ์ฒซ ๋ฒ์งธ ๋๋ ๋ง์ง๋ง ์ธ๋ฑ์ค ๋ ์ฝ๋ ์ /ํ์ Gap ์ ์ค์ ๋๋ Lock ์
๋๋ค. Gap ์์ฒด์ Lock ์ด ์ค์ ๋์๊ธฐ ๋๋ฌธ์ ์ฝ์
ํ๋ ค๋ ๊ณณ์ ๊ฐ ์กด์ฌ ์ฌ๋ถ์ ๊ด๊ณ ์์ด ๋ค๋ฅธ ํธ๋์ญ์
์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, SELECT name FROM test WHERE id >= 1 FOR UPDATE;
๋ผ๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ๋ค๋ฅธ ํธ๋์ญ์
์ด id
๊ฐ 8 ์ธ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๋ ค๊ณ ํ ๊ฒฝ์ฐ ํด๋น id
๊ฐ์ Gap Lock
์ด ์ค์ ๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ ์ฝ์
์์
์ ์ํํ ์ ์์ต๋๋ค.
์๋๋ ํด๋น ์ํฉ์ ์ฐ์ถํ๊ณ Gap Lock
์ด ์ค์ ๋ ๊ฒ์ ํ์ธํ ๊ฒฐ๊ณผ์
๋๋ค.
RECORD LOCKS space id 11 page no 4 n bits 72 index PRIMARY of table `transaction_test`.`test`
trx id 3194 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 8; hex 800000000000000a; asc ;;
1: len 6; hex 000000000c74; asc t;;
2: len 7; hex 82000000ab0110; asc ;;
3: len 4; hex 6f726361; asc orca;;
4: len 8; hex 800000000000001a; asc ;;
Next-Key Lock
Next-Key Lock
์ Record Lock
๊ณผ ํด๋น ์ธ๋ฑ์ค ๋ ์ฝ๋ ์์ Gap ์ ๋ํ Gap Lock
์ด ์กฐํฉ๋ Lock ์
๋๋ค. ์์์ ํด๋นํ๋ Next-Key Lock
์ ์๋ ๋ช
์๋ ๊ฒ๊ณผ ๊ฐ์ด ์ ์ฉ๋ฉ๋๋ค.
(negative infinity, 1]
(1, 2]
(2, 3]
(3, 6]
(6, 10]
(10, positive infinity)
๋ง์ง๋ง ๋ฒ์์ ๋ํ Next-Key Lock
์ ์ค์ ์ธ๋ฑ์ค์ ๊ฐ์ฅ ํฐ ๊ฐ๊ณผ ๊ฐ์ฅ ๋์ ๊ฐ์ ๊ฐ๋ ํ์ ์ธ๋ฑ์ค, supremum pseudo-record
๋ฅผ ํตํด Lock ์ ์ค์ ํฉ๋๋ค.
์ค์ ๋ก SELECT โฆ FROM performance_schema.data_locks;
๋ฅผ ํตํด ํ์ธํด๋ณด๋ฉด supremum pseudo-record
๊ฐ LOCK_DATA
๋ก ์กํ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
Consistent Non-Locking Reads
MySQL ์ InnoDB
๋ ๋์์ฑ ์ฑ๋ฅ์ ์ต๋ํํ๊ธฐ ์ํด Multiversion Concurrency Control, MVCC ๋ผ๋ ๊ฐ๋
์ ๋์
ํ์ต๋๋ค. ์ด๋ ๊ฒฉ๋ฆฌ ์์ค์ ๋ฐ๋ผ ์์ดํ์ง๋ง, ํน์ ์์ ์ Snapshot
์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก Locking ์ด ํ์ํ์ง ์์ Consistent Read ๋ฅผ ์ ๊ณตํ๋ค๋ ๊ณตํต์ ์ด ์์ต๋๋ค. ์ด๋ฅผ MySQL ์์ Consistent Non-Locking Read
๋ผ๊ณ ํฉ๋๋ค.
REPEATALBE READ
๊ฒฉ๋ฆฌ ์์ค์์ ์ต์ดSELECT
๋ฌธ์ด ์ํ๋ ์์ ์ ๊ธฐ์ค์ผ๋กSnapshot
์ด ์์ฑ๋์ด ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ํด ํด๋น ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์ด๋Undo Log
์ ์ ์ฅ๋ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ์ฌ๊ตฌ์ฑํฉ๋๋ค.READ COMMITTED
๊ฒฉ๋ฆฌ ์์ค์์ ๊ฐSELECT
๋ฌธ ๋ง๋คSnapshot
์ด ์ด๊ธฐํ๋๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ปค๋ฐ์ ์ํด ํด๋น ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๊ฐ์ ์ฝ๊ธฐ ์์ ์ด๋ผ๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
Locking Reads
๊ธฐ๋ณธ์ ์ธ SELECT
๋ฌธ์ ํตํด ์กฐํํ ๋ฐ์ดํฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก Non-Locking Read
์
๋๋ค. ๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์
์ ์ํด ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. InnoDB
๋ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ ๊ฐ์ง Locking Read
๋ฅผ ์ ๊ณตํฉ๋๋ค.
SELECT โฆ FOR SHARE
๋ ์ฝ์ Row ์S-Lock
์ ์ค์ ํฉ๋๋ค. ๋ค๋ฅธ ํธ๋์ญ์ ์ด Row ๋ฅผ ์ฝ์ ์ ์์ง๋ง,S-Lock
์ ์ค์ ํ ํธ๋์ญ์ ์ด ์ปค๋ฐ๋๊ธฐ ์ ๊น์ง Row ๋ฅผ ์์ ํ ์ ์์ต๋๋ค. ์์ง ์ปค๋ฐ๋์ง ์์ ๋ค๋ฅธ ํธ๋์ญ์ ์ ์ํด ํด๋น Row ๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ, ํธ๋์ญ์ ์ด ์ข ๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ๋ค ๊ฐ์ฅ ์ต์ ํ๋ ๊ฐ์ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ๋ฅผ ์ํํฉ๋๋ค.SELECT โฆ FOR UPDATE
๋ ๊ฒ์์์ ๋ฐ๊ฒฌํ ์ธ๋ฑ์ค ๋ ์ฝ๋์ ๋ํดUPDATE
๋ฌธ์ ์คํํ ๊ฒ๊ณผ ๋์ผํ๊ฒ Row ๋ฐ ๊ด๋ จ ์ธ๋ฑ์ค์ Lock ์ ์ค์ ํฉ๋๋ค. ๋ค๋ฅธ ํธ๋์ญ์ ์ ํด๋น Row ๋ฅผUPDATE
๋๋SELECT ... FOR SHARE
๋ฅผ ์ํํ๋ ๊ฒ์ด ์ ํ๋ฉ๋๋ค.
FOR SHARE
ํน์ FOR UPDATE
๋ก ์ค์ ๋ ๋ชจ๋ Lock ์ ํธ๋์ญ์
์ด ์ปค๋ฐ ๋๋ ๋กค๋ฐฑ๋ ๋ ๋ฐํ๋ฉ๋๋ค.
์ฌ๊ธฐ๊น์ง InnoDB
์ Locking, Consistent Non-Locking Read, Locking Read ๋ฑ์ ๋ํด ์์๋ณด์์ต๋๋ค. ์ด์ InnoDB
๊ฐ 4๊ฐ์ง ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค์ ์ด๋ฅผ ํตํด ์ด๋ป๊ฒ ๊ตฌํํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
READ UNCOMMITTED
๋จผ์ READ UNCOMMITTED
์
๋๋ค. ํธ๋์ญ์
์ ๋ณ๊ฒฝ ๋ด์ฉ์ด ์ปค๋ฐ์ด๋ ๋กค๋ฐฑ ์ฌ๋ถ์ ๊ด๊ณ ์์ด ๋ค๋ฅธ ํธ๋์ญ์
์ ๋ณด์ด๋ ๊ฐ์ฅ ๋ฎ์ ์์ค์ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์
๋๋ค. READ UNCOMMITTED
๊ฒฉ๋ฆฌ ์์ค์์ ์ผ๋ฐ์ ์ธ SELECT
๋ฌธ์ Non-Locking Read
๋ก ์ํ๋์ง๋ง MVCC ๋ฅผ ์ฌ์ฉํ์ง ์์ Consistent Read
๋ฅผ ๋ณด์ฅํ์ง์์ต๋๋ค.
Dirty Read
READ UNCOMMITTED
๊ฒฉ๋ฆฌ ์์ค์์ ๋ฐ์ํ ์ ์๋ ์ฝ๊ธฐ ๋ถ์ ํฉ ํ์์
๋๋ค. ๋ค๋ฅธ ํธ๋์ญ์
์ ์ํด ์ํฅ ๋ฐ์ Row ๋ฅผ ์ฝ์ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ํ์์
๋๋ค. ์ปค๋ฐ ๋๋ ๋กค๋ฐฑ์ ๊ด๊ณ ์์ด ๋ณด์ฌ์ง๊ธฐ ๋๋ฌธ์ ๋ถ์ ํํ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ํํ ์ํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ACID ์ฑ์ง์ ์ค์ํ์ง ๋ชปํ๊ธฐ์ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด InnoDB
์์ MVCC ๋ฅผ ํตํ Consistent Read
๋ฅผ ์ ๊ณตํฉ๋๋ค.
READ COMMITTED
READ COMMITTED
๊ฒฉ๋ฆฌ ์์ค๋ถํฐ MVCC ๊ฐ ์ฌ์ฉ๋์ด Consistent Read
๋ฅผ ์ง์ํ์ง๋ง ๋์ผํ ํธ๋์ญ์
๋ด์์ ๊ฐ SELECT
๋ฌธ์ ์์ฒด์ ์ผ๋ก ์๋ก์ด Snapshot
์ ์์ฑํ๊ธฐ ๋๋ฌธ์ ์์ ํ Consistent Read
๋ฅผ ๋ณด์ฅํ์ง ์์ต๋๋ค.
Locking Read
UPDATE
DELETE
๋ฌธ์ ๊ฒฝ์ฐ Record Lock
๋ง์ ์ค์ ํ๊ณ Gap Lock
์ ์ค์ ํ์ง ์๊ธฐ์ ๋ค๋ฅธ ํธ๋์ญ์
์์ ์์ ๋กญ๊ฒ Gap ์ ์ ๊ทผํ ์ ์์ต๋๋ค. Gap Lock
์ ์ค์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฒ์ ๊ฒ์๊ณผ ๊ฐ์ ์ฟผ๋ฆฌ์์ Phantom Read
ํ์ ์ญ์ ๋ฐ์ํ ์ ์์ต๋๋ค.
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
UPDATE test SET name = 'meatsby' WHERE name = 'quaritch';
์ถ๊ฐ์ ์ผ๋ก ์ ๊ทธ๋ผ์ฒ๋ผ UPDATE
์ฟผ๋ฆฌ๋ฅผ ์ํ ํ ํ
์ด๋ธ ์ค์บ ์ READ COMMITTED
๋ ์ค์บ ์ค ๋ง์ฃผ์น๋ ๋ชจ๋ ์ธ๋ฑ์ค ๋ ์ฝ๋์ X-Lock
์ ์ค์ ํ๊ณ WHERE
์ ์ด ์ํ๋ ๋ ์กฐ๊ฑด์ ๋ถํฉํ์ง ์๋ ์ธ๋ฑ์ค ๋ ์ฝ๋์ X-Lock
์ ๋ฐํํ๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๋ณ๊ฒฝํ ์ธ๋ฑ์ค ๋ ์ฝ๋๋ฅผ ์ ์ธํ ๋ค๋ฅธ ์ธ๋ฑ์ค ๋ ์ฝ๋์ Lock ์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์ ๊ณผ์ ์ถฉ๋๋ก ์ธํ ๋ฐ๋๋ฝ ๋ฐ์ ํ๋ฅ ์ ํ์ ํ ์ค์๋ค๊ณ MySQL ์ ์๊ฐํฉ๋๋ค.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
UPDATE test SET name = 'meatsby' WHERE name = 'quaritch';
๋ฐ๋ฉด REPEATABLE READ
์์ ์ค์บ ์ค ๋ง์ฃผ์น๋ ๋ชจ๋ ์ธ๋ฑ์ค ๋ ์ฝ๋์ X-Lock
์ ์ค์ ํ์ฌ ์ปค๋ฐ ๋๋ ๋กค๋ฐฑ๊น์ง Lock ์ ๋ฐํํ์ง ์์ต๋๋ค.
Non-Repeatable Read
READ COMMITTED
๊ฒฉ๋ฆฌ ์์ค๊น์ง ๋ฐ์ํ ์ ์๋ ์ฝ๊ธฐ ๋ถ์ ํฉ ํ์์
๋๋ค. ์์ ์ค๋ช
ํ ๊ฒ ์ฒ๋ผ READ COMMITTED
๊ฒฉ๋ฆฌ ์์ค์์ SELECT
๋ฌธ์ ํญ์ Snapshot
์ ์ด๊ธฐํํ๊ธฐ ๋๋ฌธ์ ํ ํธ๋์ญ์
์์ ๋์ผํ SELECT
๋ฌธ์ ์ํํด๋ ์ผ๊ด๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
REPEATABLE READ
InnoDB
์์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ ๊ณตํ๋ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ๋ก, READ COMMITTED
๊ฒฉ๋ฆฌ ์์ค๊ณผ๋ ๋ฌ๋ฆฌ ์ฒ์ ์์ฑ๋ Snapshot
์ ํตํด Consistent Read
๋ฅผ ๋ณด์ฅํฉ๋๋ค. ์ฆ, ๋์ผํ ํธ๋์ญ์
๋ด์ ์ผ๋ฐ์ ์ธ SELECT
๋ฌธ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํฉ๋๋ค.
Locking Read
UPDATE
DELETE
๋ฌธ์ ๊ฒฝ์ฐ ๊ฒ์ ์กฐ๊ฑด์ ๋ฐ๋ผ ์ฌ์ฉํ๋ Lock
์ด ๋ฌ๋ผ์ง๋๋ค.
- ๊ณ ์ ํ ๊ฒ์ ์กฐ๊ฑด์ด ์๋ ๊ณ ์ ์ธ๋ฑ์ค์ ๋ํ ์ฟผ๋ฆฌ๋
Record Lock
์ด ์ ์ฉ๋ฉ๋๋ค. - ๋ฒ์ ๊ฒ์ ์กฐ๊ฑด๊ณผ ๊ฐ์ ๋ค๋ฅธ ๊ฒ์ ์กฐ๊ฑด์ ๊ฒฝ์ฐ ์ค์บํ ์ธ๋ฑ์ค ๋ฒ์์
Gap Lock
๋๋Next-Key Lock
์ ์ค์ ํ์ฌ ๋ค๋ฅธ ํธ๋์ญ์ ์ด ํด๋น ๋ฒ์์ ์ ๊ทผํ๋ ๊ฒ์ ์ ํํฉ๋๋ค.
์๋ ์์๋ฅผ ํตํด ์ ๋ ์ํฉ์ ์ข ๋ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
# Session A
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM test WHERE id = 6 FOR UPDATE;
ํ์ฌ ์์์์ id
๊ฐ ์ธ๋ฑ์ค๋ก ์์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ณ ์ ํ id
์กฐ๊ฑด์ ํตํด FOR UPDATE
๋ฅผ ์ํํ ๊ฒฝ์ฐ ํด๋นํ๋ ์ธ๋ฑ์ค ๋ ์ฝ๋์๋ง Record Lock
์ด ์ค์ ๋ฉ๋๋ค.
# Session B
INSERT INTO test (id, name, age) VALUES (5, 'test', 26);
๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์ ์ด Gap ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ ๋ ์๋ฌด ์ ํ ์์ด ์ ์์ ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์ฝ์ ๋ฉ๋๋ค.
# Session A
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM test WHERE age = 25 FOR UPDATE;
๋ฐ๋ฉด age
์ ๊ฐ์ด ํ์ฌ ํ
์ด๋ธ ์ํ์์ ๊ณ ์ ํ์ง๋ง ์ธ๋ฑ์ค๊ฐ ์๋ ์กฐ๊ฑด์ ํตํด FOR UPDATE
๋ฅผ ์ํํ ๊ฒฝ์ฐ ํ ํ
์ด๋ธ ์ค์บ์ ํตํด ํด๋น ์ธ๋ฑ์ค ๋ ์ฝ๋๋ฅผ ํ์ํ๊ธฐ ๋๋ฌธ์ ๊ทธ ๊ณผ์ ์์ ๋ง์ฃผ์น ๋ชจ๋ ์ธ๋ฑ์ค ๋ ์ฝ๋์ X-Lock
์ด ์ ์ฉ๋ฉ๋๋ค.
# Session B
INSERT INTO test (id, name, age) VALUES (5, 'test', 26);
์ด ์ํ์์ ๋ค๋ฅธ ํธ๋์ญ์
์ด Gap ์ id
๊ฐ 5 ์ธ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๋ ค๊ณ ํ ๊ฒฝ์ฐ id
๊ฐ 6 ์ธ ์ธ๋ฑ์ค ๋ ์ฝ๋์ Gap Lock
์ผ๋ก ์ธํด ๋ฐ์ดํฐ ์ฝ์
์ด ์ ํ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด InnoDB
์์ REPEATABLE READ
์์ค์์๋ Phantom Read
ํ์์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
Phantom Read
A : START TRANSACTION;
A : SELECT * FROM test; # ์ต์ด Snapshot ์์ฑ
B : INSERT INTO test (id, name, age) VALUES (5, 'test', 26); # Lock ์ด ๊ฑธ๋ ค์์ง ์๊ธฐ ๋๋ฌธ์ Gap ์ ๋ฐ์ดํฐ ์ฝ์
๊ฐ๋ฅ
A : SELECT * FROM test; # ์ต์ด Snapshot ์ ๊ทธ๋๋ก ์ฌ์ฉ
A : UPDATE test SET name = 'twenty-six' WHERE age = 26; # Locking Read ๋ฅผ ํตํด ์๋กญ๊ฒ ์ฝ์ ํ UPDATE
A : SELECT * FROM test; # Snapshot ์ด ์ด๊ธฐํ๋์ด Phantom Read ๋ฐ์
์ฌ์ ํ ์ด๋ฐ ๊ตฌ์กฐ์๋ ๋ถ๊ตฌํ๊ณ REPEATABLE READ
์์ Phantom Read
๊ฐ ๋ฐ์ํ ์ ์๋ ์ํฉ์ด ์์ต๋๋ค.
์ ์ํฉ์ฒ๋ผ ๋ค๋ฅธ ํธ๋์ญ์
์ด ์ถ๊ฐํ ๋ ์ฝ๋์ UPDATE
์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ฒ ๋ ๊ฒฝ์ฐ, ์ฒซ SELECT
์ฟผ๋ฆฌ๋ก ์์ฑ๋ Snapshot
์๋ ์กด์ฌํ์ง ์์ง๋ง ์ค์ ๋์คํฌ์๋ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ํด๋น ๋ ์ฝ๋๊ฐ ์ํฅ์ ๋ฐ์ ์ดํ SELECT
์ฟผ๋ฆฌ๋ฅผ ์ํํ ๋ Snapshot
์ด ์ด๊ธฐํ๋๋ ์์ ์ ํด๋น ํ์์ ๋ฐ๊ฒฌํ ์ ์์ต๋๋ค.
์ฆ, Consistent Non-Locking Read
์ Locking Read
์ ์กฐํฉ ๋๋ฌธ์ ๋ฐ์ํ ์ ์๋ ํ์์
๋๋ค.
์์ ์ค๋ช
ํ ๊ฒ ์ฒ๋ผ ์ผ๋ฐ์ ์ธ SELECT
๋ฌธ์ Non-Locking Read
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์ UPDATE
๋ฅผ ์ํ SELECT
๋ SELECT โฆ FOR UPDATE
์ ๊ฐ์ด Locking Read
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ ํฉํฉ๋๋ค.
๋ฐ๋ผ์, ์ ์์์์ ์ฐ์ถํ๋ ์ํฉ ์์ฒด๊ฐ ๋ถ์ ์ ํ๋ค๊ณ ์๊ฐํ์ง๋ง, ์ฌ์ ํ ๋ฐ์ํ ์ ์๋ ํน์ ์ํฉ์ด ์กด์ฌํ๋ค๋ ์ฌ์ค์ ์๊ณ ์๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
SERIALIZABLE
๋ง์ง๋ง SERIALIZABLE
์ ๊ฐ์ฅ ๋์ ์์ค์ ๊ฒฉ๋ฆฌ ๋ ๋ฒจ์
๋๋ค. ์ด๋ฆ์ฒ๋ผ ์ง๋ ฌํ๋ ๋ฐฉ์์ฒ๋ผ ์๋ํด์ผํฉ๋๋ค. InnoDB
์์ ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ์ผ๋ฐ์ ์ธ SELECT
๋ฌธ์ ๋ชจ๋ SELECT โฆ FOR SHARE
๋ฌธ์ผ๋ก ๋ณํํ์ฌ S-Lock
์ ํตํ Locking Read
๋ฅผ ์ํํ๊ฒ๋ ํฉ๋๋ค.
๊ธ ์ด๋ฐ๋ถ ์ค๋ช
๋์ด์๋ฏ์ด S-Lock
์ ๋ค๋ฅธ ํธ๋์ญ์
๋ ๋
๋ฆฝ์ ์ผ๋ก ์ค์ ์ด ๊ฐ๋ฅํ์ฌ S-Lock
์ด ์ค์ ๋ ๋ ์ฝ๋๋ฅผ ์ฝ์ ์ ์์ง๋ง ์ต์ด๋ก S-Lock
์ ์ค์ ํ ํธ๋์ญ์
์ด ์ข
๋ฃ๋๊ธฐ ์ ๊น์ง ๋ณ๊ฒฝ์ ๊ฐํ ์ ์์ต๋๋ค.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM test;
์ ๊ทธ๋ฆผ์ฒ๋ผ ๋จ์ํ SELECT
๋ฌธ์ ์ํํด๋ ๋ชจ๋ ๋ ์ฝ๋์ S-Lock
์ด ์ค์ ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๋ง๋ฌด๋ฆฌ
์ฌ๊ธฐ๊น์ง MySQL ์ InnoDB
๊ฐ 4๊ฐ์ง ๊ฒฉ๋ฆฌ ์์ค์ ๊ตฌํํ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์์ต๋๋ค. ๊ฒฉ๋ฆฌ ์์ค์ ๋์์ฑ๊ณผ ๊ฒฉ๋ฆฌ์ฑ์ Trade-Off ์ธ ๋งํผ ์์ธํ ์๊ณ ์ฌ์ฉํ๋ฉด ๋ ์ข์ ํจ๊ณผ๋ฅผ ๋ํ๋ผ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
MySQL ์ ๋ค๋ฅธ DBMS ๋ฒค๋๋ค๊ณผ๋ ๋ฌ๋ฆฌ InnoDB
๋ฅผ ํตํด REPEATABLE READ
์์๋ ์ถฉ๋ถํ ๊ฒฉ๋ฆฌ์ฑ์ ๋ณด์ฌ์ฃผ๊ณ ์์ต๋๋ค. ํ์ง๋ง ์ฌ๋ฌ๊ฐ์ง Locking ๊ธฐ๋ฒ์ ํ์ฉํ์ฌ ๊ฒฉ๋ฆฌ ์์ค์ ๊ตฌํํ๊ธฐ ๋๋ฌธ์ Locking ์ผ๋ก ์ธํด ๋ฐ์ํ ์ ์๋ ์ฌ๋ฌ ๋ฌธ์ ์ ์ญ์ ์ถฉ๋ถํ ์ดํดํ๋ ๊ฒ์ด ์ค์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.