About
home
Tmax OpenSQL
home
๐Ÿ’Ž

6. PostgreSQL์˜ Concurrency Control

์ž‘์„ฑ์ž
JBH
SHC

Concurrency Control

Concurrency Control์€ DBMS์—์„œ ํŠน์ • ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋™์‹œ ์ ‘๊ทผ์„ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. Concurrency Control์€ Multi-version Concurrency Control (MVCC), Strict Two-phase Locking (S2PL), Optimistic Concurrency Control (OCC) ๋“ฑ ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. PostgreSQL์€ MVCC ๋ฐฉ์‹์„ ํ™œ์šฉํ•˜์—ฌ Concurrency Control์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
MVCC๋Š” ๊ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ ์‹œ์ ์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๋ฒ„์ „์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ๋ฐ์ดํ„ฐ๋Š” 1๊ฐœ๋กœ ๋ณด์—ฌ์ง€์ง€๋งŒ ์‹ค์ œ๋กœ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋Š” ์—ฌ๋Ÿฌ ๋ฒ„์ „์˜ ๋ฐ์ดํ„ฐ(๋ ˆ์ฝ”๋“œ)๋กœ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋ฒˆ ์žฅ์—์„œ๋Š” PostgreSQL์—์„œ MVCC๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ณ  ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Isolation Level, Lost Update ๋“ฑ DBMS์—์„œ ์ •์˜ํ•˜๋Š” Concurrency ์ด์Šˆ๋“ค์ด ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃจ์–ด์ง€๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
Reference. Bernstein, Philip A., and Nathan Goodman. "Concurrency control in distributed database systems."ย ACM Computing Surveys (CSUR) 13.2 (1981): 185-221.

Transaction ID

๋Œ€๋‹ค์ˆ˜์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๊ณ  ์ด๋ฅผ ์œ„ํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋ผ๋Š” ๊ฐœ๋…์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. PostgreSQL๋„ ์˜ˆ์™ธ ์—†์ด ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ ๋ฌธ๋‹จ์—์„œ๋Š” PostgreSQL์—์„œ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ์— ๋Œ€ํ•˜์—ฌ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
PostgreSQL์€ 32-bit unsigned integer(1 ~ 2^32 -1)๋กœ ํ‘œํ˜„๋˜์–ด ์•ฝ 42์–ต ๊ฐœ์˜ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ  1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘๋  ๋•Œ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(0์€ invalid tx_id๋กœ ์˜ˆ์•ฝ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค). PostgreSQL์€ ์ด๋ฅผ ์›ํ˜•(Circular) ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋ˆˆ์น˜๊ฐ€ ๋น ๋ฅด๋‹ค๋ฉด ์ด ๊ตฌ์กฐ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜๋ฌธ์ ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ€œํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋ฅผ ๋‹ค ์“ฐ๊ณ  ํ•œ๋ฐ”ํ€ด ๋Œ๋ฉด ์–ด๋–กํ•˜์ง€?โ€ ์ด ๊ฐœ๋…์€ Vacuum์—์„œ ์„ค๋ช…ํ•  ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋•Œ๊นŒ์ง€ ์ด ์˜๋ฌธ์„ ๋งˆ์Œ์— ํ’ˆ๊ณ  ์žˆ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Tuple

๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ตœ์ดˆ๋กœ ๊ณ ์•ˆํ•œ ์—๋“œ๊ฑฐ F. ์ปค๋“œ๋Š” Relation์€ ํŠœํ”Œ(Tuple)๋“ค์˜ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ์ •์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ๋Š” ์ฃผ๋กœ Relation์€ ํ…Œ์ด๋ธ”(Table), ํŠœํ”Œ์€ ํ–‰(Row)์˜ ํ˜•ํƒœ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ๊ด€์ ์—์„œ๋Š” Relation์€ ํŒŒ์ผ, ํŠœํ”Œ์€ ๊ทธ ์•ˆ์— ๊ธฐ๋ก๋œ ๋ ˆ์ฝ”๋“œ(Record)๋“ค์— ๋Œ€์‘ํ•ฉ๋‹ˆ๋‹ค.
ํ›„์ˆ ํ•  ๋‚ด์šฉ์„ ์›ํ™œํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์›๋ก ์ ์ธ ์ •์˜๋ฅผ ํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ณ  ๋„˜์–ด๊ฐˆ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃฐ Concurrency Control์€ ์šฐ๋ฆฌ๊ฐ€ ์ต์ˆ™ํ•œ ๊ฐœ๋…์ธ ํ…Œ์ด๋ธ”๊ณผ ํ–‰๊ณผ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€์ ์ด ์•„๋‹Œ ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ๊ด€์ ์—์„œ ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (์œ„ ๊ฐœ๋…์€ ํ•„์ˆ˜์ ์œผ๋กœ ์ดํ•ด์•ผํ•˜๋Š” ํ›„์ˆ ํ•  ๋‚ด์šฉ๋“ค์˜ ๊ธฐ๋ณธ ์ „์ œ์ž…๋‹ˆ๋‹ค. ์ด ๋ฌธ์žฅ์ด ์ดํ•ด๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด Concurrency Control ํ•ญ๋ชฉ์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ฝ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.)
Reference. Codd, Edgar F. "A relational model of data for large shared data banks."ย Communications of the ACM 13.6 (1970): 377-387.
PostgreSQL์—์„œ๋Š” Relation์€ ํ…Œ์ด๋ธ”, ์ธ๋ฑ์Šค, ์‹œํ€€์Šค ๋“ฑ์„ ํฌํ•จํ•˜๋Š” ๊ฐœ๋…์œผ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํŠœํ”Œ ์—ญ์‹œ ํ•ด๋‹น ํŠœํ”Œ์ด ํฌํ•จ๋œ Relation์— ๋”ฐ๋ผ Heap Tuple, Index Tuple ๋“ฑ์œผ๋กœ ๋‚˜๋‰˜์–ด์ง‘๋‹ˆ๋‹ค. PostgreSQL์—์„œ ํŠœํ”Œ์€ ๋ฐ์ดํ„ฐ์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ๋ฐ์ดํ„ฐ์— ๋ณ€๊ฒฝ(INSERT, UPDATE, DELETE)์ด ๋ฐœ์ƒํ•  ๋•Œ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
๋ณธ๋ฌธ์—์„œ๋Š” ํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ Concurrency Control์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ง„ํ–‰ํ•  ๊ฒƒ์ด๋ฉฐ, ์ด์— ๋”ฐ๋ผ ํž™ ํŠœํ”Œ์„ ๊ธฐ์ค€์œผ๋กœ ์„ค๋ช…์„ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
PostgreSQL ํž™ ํŠœํ”Œ์„ ํ‘œํ˜„ํ•˜๋Š” ๊ตฌ์กฐ์ฒด์ธ HeapTupleData๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ์žฅ์—์„œ๋Š” ํ›„์ˆ ํ•  ๋‚ด์šฉ์„ ์ดํ•ดํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๊ฐ’์— ๋Œ€ํ•ด์„œ๋งŒ ์„ธ๋ถ€์ ์ธ ์„ค๋ช…์„ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
HeapTupleData Struct
์ด์ค‘ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ 4๊ฐ€์ง€ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ Concurrency Control์„ ์„ค๋ช…ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
โ€ข
t_xmin: ํŠœํ”Œ์ด INSERT ๋  ๋•Œ์˜ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””
โ€ข
t_xmax: ํŠœํ”Œ์ด DELETE ๋˜๊ฑฐ๋‚˜ LOCKING ๋ ๋•Œ์˜ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””
โ€ข
t_cid: ํŠœํ”Œ์˜ INSERT, DELETE์— ๋Œ€ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด COMMAND ID (0๋ถ€ํ„ฐ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.)
โ€ข
t_ctid: ํ˜„์žฌ ํŠœํ”Œ(์ž๊ธฐ ์ž์‹ )์˜ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋”” ํ˜น์€ ์ƒˆ๋กœ์šด ํŠœํ”Œ(๋‹ค์Œ ๋ ˆ์ฝ”๋“œ)์˜ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””

Operation

๋ณธ ๋ฌธ๋‹จ์—์„œ๋Š” ๊ฐ ์ฟผ๋ฆฌ๊ฐ€ ์ˆ˜ํ–‰๋  ๋•Œ ํŠœํ”Œ์ด ์–ด๋–ป๊ฒŒ ์ถ”๊ฐ€๋˜๊ณ  ๋ฐ”๋€Œ๋Š”์ง€์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ผ๋‹จ ์ฟผ๋ฆฌ์˜ INSERT, UPDATE, DELETE์™€ ํŠœํ”Œ์— ๋Œ€ํ•œ INSERT, DELETE๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ณธ ๋ฌธ๋‹จ์—์„œ๋Š” ์ด๋ฅผ ์œ„ํ•ด ํŠœํ”Œ์— ๋Œ€ํ•œ INSERT, DELETE๋ฅผ ๊ฐ๊ฐ T_INSERT, T_DELETE๋กœ ๋ช…์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
์Šคํฌ์ผ๋Ÿฌ

Insert

๋‹ค์Œ ์ฝ”๋“œ์™€ ํ‘œ๋Š” ๊ฐ๊ฐ ํ•˜๋‚˜์˜ INSERT๋ฅผ ํฌํ•จํ•˜๋Š” ํŠธ๋žœ์žญ์…˜๊ณผ ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์™„๋ฃŒ๋œ ํ›„์˜ ํŠœํ”Œ์˜ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
# txid = 100 BEGIN; INSERT INTO example_table VALUES('A'); -- COMMAND 0 COMMIT;
SQL
๋ณต์‚ฌ
1
100
0
0
(0, 1)
โ€˜Aโ€™
COMMAND 0์€ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๊ฐ€ 100์ผ ๋•Œ ์ˆ˜ํ–‰๋˜์–ด 1๋ฒˆ ํŠœํ”Œ์ด T_INSERT ๋˜์—ˆ์œผ๋ฏ€๋กœ t_xmin = 100์ž…๋‹ˆ๋‹ค.
์œ„ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ 1๋ฒˆ ํŠœํ”Œ์€ T_DELETE ๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ t_xmax = 0 ์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์—์„œ 1๋ฒˆ ํŠœํ”Œ์€ ์ฒซ๋ฒˆ์งธ COMMAND์ด๋‹ค. Command ID๋Š” 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ t_cid = 0์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์—์„œ ์ƒˆ๋กœ ์ƒ์„ฑ๋œ โ€˜Aโ€™๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ROW๋Š” ์œ„ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๋ณ€๊ฒฝ๋œ ์ ์ด ์—†์œผ๋ฏ€๋กœ 1๋ฒˆ ํŠœํ”Œ์˜ t_ctid๋Š” ์ž๊ธฐ ์ž์‹ ์„ ์ง€์นญํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. (0, 1)์˜ ์˜๋ฏธ๋Š” 0๋ฒˆ ํŽ˜์ด์ง€์˜ Offset = 1์— ํ•ด๋‹น ํŠœํ”Œ์ด ์œ„์น˜ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

Update

# txid = 105 BEGIN; UPDATE example_table SET data = 'B' WHERE ...; -- COMMAND 0 UPDATE example_table SET data = 'C' WHERE ...; -- COMMAND 1 COMMIT;
SQL
๋ณต์‚ฌ
๋‹ค์Œ ํ‘œ๋Š” COMMAND 0์ด ์ˆ˜ํ–‰๋œ ์ดํ›„์˜ ํŠœํ”Œ์˜ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
no
t_xmin
t_xmax
t_cid
t_ctid
data
1
100
105
0
(0, 2)
โ€˜Aโ€™
2
105
0
0
(0, 2)
โ€˜Bโ€™
์ƒ์ˆ ํ•˜์˜€๋˜ INSERT ์˜ˆ์‹œ์—์„œ ์ด์–ด์ง„ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. 1๋ฒˆ ํŠœํ”Œ์€ INSERT ์˜ˆ์‹œ์—์„œ T_INSERT๋œ ํŠœํ”Œ์ž…๋‹ˆ๋‹ค. COMMAND 0 ์ˆ˜ํ–‰ ์ดํ›„, 1๋ฒˆ ํŠœํ”Œ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ณ€ํ™”๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
t_xmin์˜ ๊ฐ’์€ T_INSERT ์‹œ์ ์˜ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋ฅผ ์˜๋ฏธํ•˜๋ฏ€๋กœ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. t_xmax์˜ ๊ฒฝ์šฐ, 2๋ฒˆ ํŠœํ”Œ์ด T_INSERT ๋˜๋ฉด์„œ T_DELETE๋œ ์ƒํ™ฉ์ด๋ฏ€๋กœ t_xmax๋Š” T_DELETE๊ฐ€ ์ด๋ฃจ์–ด์ง„ ์‹œ์  ์ฆ‰, COMMAND 0์ด ์ˆ˜ํ–‰๋œ ์‹œ์ ์ธ 105๋กœ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค. t_cid๋Š” ํ•ด๋‹น ํŠœํ”Œ์„ ๋ฐœ์ƒ์‹œํ‚จ COMMAND ID์ด๋ฏ€๋กœ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. t_ctid๋Š” 1๋ฒˆ ํŠœํ”Œ์ด T_DELETE๋˜๊ณ  ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๋ ˆ์ฝ”๋“œ์ธ 2๋ฒˆ ํŠœํ”Œ์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•ด๋‹น ๊ฐ’์€ 2๋ฒˆ ํŠœํ”Œ์˜ ์œ„์น˜๋กœ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.
1๋ฒˆ ํŠœํ”Œ์˜ ๊ฒฝ์šฐ, ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๊ฐ€ 105์ธ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์ˆ˜ํ–‰๋˜์—ˆ์œผ๋ฏ€๋กœ t_xmin = 105 ์ž…๋‹ˆ๋‹ค. ์œ„ ํŠธ๋žœ์žญ์…˜์˜ ์ฒซ๋ฒˆ์งธ COMMAND ์ด๋ฏ€๋กœ COMMAND ID๋Š” 0 ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, t_cid = 0 ์ด ๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋ง‰ T_INSERT๋œ ํŠœํ”Œ์ด๋ฏ€๋กœ t_xmax = 0 ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ํŠœํ”Œ์ด ์—†์œผ๋ฏ€๋กœ t_ctid๋Š” ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋‹ค์Œ ํ‘œ๋Š” COMMAND 1์ด ์ˆ˜ํ–‰๋œ ์ดํ›„์˜ ํŠœํ”Œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
no
t_xmin
t_xmax
t_cid
t_ctid
data
1
100
105
0
(0, 2)
โ€˜Aโ€™
2
105
105
0
(1, 1)
โ€˜Bโ€™
3
105
0
1
(1, 1)
โ€˜Cโ€™
COMMAND 0, COMMAND 1 ๋ชจ๋‘ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๊ฐ€ 105 ์ผ ๋•Œ ์ˆ˜ํ–‰๋˜์–ด ํ•ด๋‹น ํŠœํ”Œ์ด T_INSERT ๋˜์—ˆ์œผ๋ฏ€๋กœ t_xmin์€ 2, 3๋ชจ๋‘ 105 ์ž…๋‹ˆ๋‹ค.
2๋ฒˆ ํŠœํ”Œ์˜ ๊ฒฝ์šฐ, COMMAND 1์ด ์ˆ˜ํ–‰๋˜๋ฉด์„œ T_DELETE ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์‹œ์  ์—ญ์‹œ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๊ฐ€ 105์ผ ๋•Œ์ด๋ฏ€๋กœ 2๋ฒˆ ํŠœํ”Œ์˜ t_xmax๋Š” 105 ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 3๋ฒˆ ํŠœํ”Œ์˜ ๊ฒฝ์šฐ, ์ƒˆ๋กœ T_INSERT ๋˜์—ˆ์œผ๋ฏ€๋กœ t_xmax๋Š” 0 ์ž…๋‹ˆ๋‹ค.
ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ Command ID๋Š” 0๋ถ€ํ„ฐ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์œ„ ์˜ˆ์‹œ์—์„œ COMMAND 0, COMMAND 1๋กœ ๊ฐ ์ฟผ๋ฆฌ๋ฅผ ์ง€์นญํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. 2๋ฒˆ ํŠœํ”Œ์€ COMMAND 0 ์— ๋Œ€ํ•œ ํŠœํ”Œ์ด๋ฏ€๋กœ t_cid๋Š” 0 ์ž…๋‹ˆ๋‹ค. ๊ฐ™์€ ์›๋ฆฌ๋กœ 3๋ฒˆ ํŠœํ”Œ์˜ t_cid = 1 ์ž…๋‹ˆ๋‹ค.
๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด 2๋ฒˆ ํŠœํ”Œ์ด T_DELETE๋˜๊ณ  3๋ฒˆ ํŠœํ”Œ์ด T_INSERT ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 2๋ฒˆ ํŠœํ”Œ์˜ ๋‹ค์Œ ๊ฐ’์€ 3๋ฒˆ ํŠœํ”Œ์ด๋ฏ€๋กœ 2๋ฒˆ ํŠœํ”Œ์˜ t_ctid = (1, 1)์ด ๋˜๊ณ  3๋ฒˆ ํŠœํ”Œ์€ ๋‹ค์Œ ํŠœํ”Œ์ด ์—†์–ด ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๋ฏ€๋กœ t_ctid = (1, 1) ์ด ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ t_ctid์˜ ์ฒซ๋ฒˆ์งธ ๊ฐ’์€ ํŽ˜์ด์ง€ Number๋ฅผ ์ง€์นญํ•˜๊ณ  ๋‘๋ฒˆ์งธ ๊ฐ’์€ ํŽ˜์ด์ง€ ๋‚ด์—์„œ ํ•ด๋‹น ํŠœํ”Œ์˜ Offset์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์œ„ ์˜ˆ์‹œ์—์„œ๋Š” COMMAND 1 ์ˆ˜ํ–‰ ๊ฒฐ๊ณผ ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๊ณ  3๋ฒˆ ํŠœํ”Œ์€ ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€์— ์ถ”๊ฐ€๋˜์—ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Delete

# txid = 111 BEGIN; DELETE FROM example_table WHERE ...; -- COMMAND 0 COMMIT;
SQL
๋ณต์‚ฌ
no
t_xmin
t_xmax
t_cid
t_ctid
data
1
100
105
0
(0, 2)
โ€˜Aโ€™
2
105
105
0
(1, 1)
โ€˜Bโ€™
3
105
111
1
(1, 1)
โ€˜Cโ€™
PostgreSQL์€ DELETE๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์„ ๋•Œ, ์‹ค์ œ๋กœ ํŠœํ”Œ์„ ์‚ญ์ œํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด์˜ ํŠœํ”Œ(๋งˆ์ง€๋ง‰ ๋ ˆ์ฝ”๋“œ)์˜ t_xmax ๊ฐ’๋งŒ์„ ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๋กœ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ๊ธฐ์กด์— ์กด์žฌํ–ˆ๋˜ 3๋ฒˆ ํŠœํ”Œ์˜ t_xmax ๊ฐ’๋งŒ์„ 111๋กœ ๊ฐฑ์‹ ํ•˜์˜€์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์œ„์˜ ์Šคํฌ์ผ๋Ÿฌ ํ•ญ๋ชฉ์„ ์ฝ์ง€ ์•Š์•˜๋‹ค๋ฉด ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€ ์ฝ์–ด๋ณด๋ฉด์„œ ์ •๋ฆฌํ•ด๋ณด๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Commit Log

PostgreSQL์€ ๊ฐ ํŠธ๋žœ์žญ์…˜์˜ ์ƒํƒœ๋ฅผ Commit Log์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. Clog๋Š” ํŠธ๋žœ์žญ์…˜ ์ˆ˜ํ–‰ ์ค‘, ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹น๋˜์–ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
PostgreSQL์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜์˜ ์ƒํƒœ๋ฅผ IN_PROGRESS, COMMITTED, ABORTED, SUB_COMMITTED๋กœ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ๋ณธ ๋ฌธ์„œ์—์„œ๋Š” Sub-Transaction์˜ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” SUB_COMMITTED ์ƒํƒœ์— ๋Œ€ํ•ด์„œ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.
IN_PROGRESS๋Š” ํ˜„์žฌ ์ˆ˜ํ–‰์ค‘์ธ ํŠธ๋žœ์žญ์…˜์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ƒ์„ฑ๋œ ํŠœํ”Œ์€ ์ž๊ธฐ ์ž์‹ ์—๊ฒŒ๋Š” ๋ณด์ด์ง€๋งŒ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—๋Š” ๋ณด์ด์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค. COMMITTED๋Š” ์ปค๋ฐ‹์ด ์™„๋ฃŒ๋œ ํŠธ๋žœ์žญ์…˜์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์€ ์ด๋ฏธ ์ข…๋ฃŒ๋˜์—ˆ๊ณ  ์—ฌ๊ธฐ์„œ ์ƒ์„ฑ๋œ ํŠœํ”Œ์€ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—๋„ ๋ณด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ABORTED๋Š” ์ค‘๋‹จ๋œ ํŠธ๋žœ์žญ์…˜์ด๋‹ค. ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์€ ์ข…๋ฃŒ๋˜์—ˆ์œผ๋‚˜, ์ค‘๋‹จ๋˜์—ˆ์œผ๋ฏ€๋กœ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์— ๋ณด์—ฌ์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

Transaction Snapshot

ํŠธ๋žœ์žญ์…˜ ์Šค๋ƒ…์ƒท์€ ํŠน์ • ์‹œ์ ์˜ ๊ฐ ํŠธ๋žœ์žญ์…˜์— ๋Œ€ํ•œ Active ์—ฌ๋ถ€๋ฅผ ๊ธฐ๋กํ•œ๋‹ค. PostgreSQL์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜์ด IN_PROGRESS ์ƒํƒœ์ด๊ฑฐ๋‚˜ ์•„์ง ์‹œ์ž‘ํ•˜์ง€ ์•Š์€ ํŠธ๋žœ์žญ์…˜์„ Active๋ผ๊ณ  ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
ํŠธ๋žœ์žญ์…˜ ์Šค๋ƒ…์ƒท์€ txid_current_snapshot()์„ ํ†ตํ•ด ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ์Šค๋ƒ…์ƒท์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.
SELECT txid_current_snapshot(); -- xmin:xmax:xip_list -- 100:108:100,101,106
SQL
๋ณต์‚ฌ
ํŠธ๋žœ์žญ์…˜ ์Šค๋ƒ…์ƒท์˜ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
โ€ข
xmin: ํ™œ์„ฑ ์ƒํƒœ์ธ ํŠธ๋žœ์žญ์…˜ ์ค‘ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ(ํŠธ๋žœ์žญ์…˜ ์•„์ด๋””๊ฐ€ ๋‚ฎ์€) ํŠธ๋žœ์žญ์…˜์˜ ์•„์ด๋””
โ€ข
xmax: ์•„์ง ํ• ๋‹น๋˜์ง€ ์•Š์€ ํŠธ๋žœ์žญ์…˜ ์ค‘ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ(์ฒซ๋ฒˆ์งธ) ํŠธ๋žœ์žญ์…˜์˜ ์•„์ด๋””
โ€ข
xip_list: ์Šค๋ƒ…์ƒท ์‹œ์ ์˜ ํ™œ์„ฑ๋œ ํŠธ๋žœ์žญ์…˜์˜ ์•„์ด๋””์˜ ๋ฆฌ์ŠคํŠธ

Visibility

PostgreSQL๋Š” ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ(Isolation)๋ฅผ ์œ„ํ•ด ํŠน์ • ํŠธ๋žœ์žญ์…˜ ์ˆ˜ํ–‰ ์‹œ, ์–ด๋–ค ํŠœํ”Œ์ด ๋ณด์—ฌ์ง€๊ณ  ์•ˆ ๋ณด์—ฌ์งˆ์ง€๋ฅผ ๊ฒฐ์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Visibility(๊ฐ€์‹œ์„ฑ)๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. Visibility๋Š” ๊ฐ ํŠธ๋žœ์žญ์…˜์—์„œ ํŠน์ • ํŠœํ”Œ์˜ ๊ฐ€์‹œ์„ฑ์„ ์˜๋ฏธํ•˜๋ฉฐ Visibility Rule์— ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์ˆ˜ ๋งŽ์€ ๊ทœ์น™์ด ์กด์žฌํ•˜์ง€๋งŒ ๋ณธ ๋ฌธ์„œ์—์„œ๋Š” ๋ณดํŽธ์ ์ธ ๋‹ค์Œ 11๊ฐ€์ง€ ๊ทœ์น™์— ๋Œ€ํ•ด์„œ๋งŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ƒฅ ๋ด…์‹œ๋‹ค.

Rule #
status (t_xmin)
status (t_xmax)
value (t_xmin)
value (t_xmax)
snapshot (t_xmin)
snapshot (t_xmax)
visibility
1
ABORTED
X
2
IN_PROGRESS
CURRENT
ZERO
O
3
IN_PROGRESS
CURRENT
NON-ZERO
X
4
IN_PROGRESS
OTHER
X
5
COMMITTED
ACTIVE
X
6
COMMITTED
ABORTED
O
7
COMMITTED
ZERO
O
8
COMMITTED
IN_PROGRESS
CURRENT
X
9
COMMITTED
IN_PROGRESS
NON-ZERO
O
10
COMMITTED
COMMITTED
ACTIVE
O
11
COMMITTED
COMMITTED
IN-ACTIVE
X

์ˆฒ์„ ๋ด…์‹œ๋‹ค.

โ€ข
Rule 1 : ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ(T_INSERT) ํŠธ๋žœ์žญ์…˜(t_xmin)์€ ABORTED๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜ ์ž์ฒด๊ฐ€ ์ค‘๋‹จ๋˜์—ˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ All or Nothing์˜ Nothing์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•ด๋‹น ํŠœํ”Œ์€ ๋ณด์—ฌ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
โ€ข
Rule 2,3,4 : ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์ด ์•„์ง IN_PROGRESS ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ํ•ด๋‹น ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ๋งŒ ๋ณด์—ฌ์ง‘๋‹ˆ๋‹ค. ๋˜ํ•œ ํ•ด๋‹น ํŠœํ”Œ์ด UPDATE, DELETE์— ์˜ํ•ด T_DELETE ๋˜์—ˆ์„ ๋•Œ์—๋Š” ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜์—์„œ๋„ ๋ณด์—ฌ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
โ€ข
Rule 5,6,7,8,9,10,11 : ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์ด COMMITTED ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹ ๋œ ์ดํ›„์— ์ƒ์„ฑ๋œ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ํ•ด๋‹น ํŠœํ”Œ์ด ๋ณด์—ฌ์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, ์œ„์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋˜ํ•œ ํ•ด๋‹น ํŠœํ”Œ์ด UPDATE, DELETE์— ์˜ํ•ด T_DELETE ๋˜์—ˆ์„ ๋•Œ์—๋Š” ๋ณด์—ฌ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚˜๋ฌด๋ฅผ ๋ด…์‹œ๋‹ค.

โ€ข
Rule 1์€ โ€œStatus(t_xmin) = ABORTEDโ€ ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์ด ์ค‘๋‹จ๋˜์—ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜์€ ์›์ž์„ฑ์— ์˜ํ•ด All or Nothing์ž…๋‹ˆ๋‹ค. ์ค‘๋‹จ๋œ ํŠธ๋žœ์žญ์…˜์˜ ํŠœํ”Œ์€ ๋ฐ˜์˜๋˜์ง€ ์•Š์•„์•ผํ•˜๋ฏ€๋กœ ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์—์„œ ํ•ด๋‹น ํŠœํ”Œ์€ ๋ณผ ์ˆ˜ ์—†์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, Invisible ์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 2๋Š” โ€œStatus(t_xmin) = IN_PROGRESSโ€. ํ•ด๋‹น ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์ด ์•„์ง ์ˆ˜ํ–‰ ์ค‘์ด๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์•„์ง ์ปค๋ฐ‹๋˜์ง€๋„ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•ด๋‹น ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ๋งŒ ๋ณผ ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. โ€œt_xmin = current_txidโ€ ์ฆ‰, ํ•ด๋‹น ํŠœํ”Œ์€ ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์—์„œ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ T_DELETE๋˜์—ˆ๋Š”์ง€๋งŒ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. t_xmax = 0 ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ƒ์ˆ ํ•œ Operation ๋ฌธ๋‹จ์—์„œ t_xmax๊ฐ€ 0์ผ ๊ฒฝ์šฐ์—๋Š” T_DELETE๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ์‚ฌ์‹ค์„ ์–ธ๊ธ‰ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 2์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Visible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 3๋Š” Rule 2์™€ ๋‹ฌ๋ฆฌ t_xmax โ‰  0 ์ด๋ฏ€๋กœ ํ•ด๋‹น ํŠœํ”Œ์€ ์ด๋ฏธ T_DELETE ๋˜์—ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. UPDATE๋กœ ์ธํ•ด ๋‹ค์Œ ๋ฒ„์ „์˜ ํŠœํ”Œ์ด ์กด์žฌํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 3์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Invisible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 4์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ ์•„์ง IN_PROGRESS ์ƒํƒœ์ด๋‹ˆ ์ปค๋ฐ‹๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ๋ณด์—ฌ์ง€์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค. โ€œt_xmin โ‰  current_txidโ€์— ์˜ํ•ด ํ•ด๋‹น ํŠœํ”Œ์€ ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜๊ณผ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 4์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Invisible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 5๋Š” ์กฐ๊ธˆ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ์œ„์—์„œ ๋ถ„๋ช… IN_PROGRESS ์ด๊ฑฐ๋‚˜ ํ• ๋‹น๋˜์ง€ ์•Š์€ ํŠธ๋žœ์žญ์…˜์ด Active๋ผ๊ณ  ํ–ˆ๋Š”๋ฐ, Rule 5๋Š” COMMITTED ์ƒํƒœ์ž„์—๋„ Active๋ผ๊ณ  ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด ๋‹ค๋ฅธ Isolation Level(ํ›„์ˆ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค)์„ ๊ฐ€์ง„ ์„ธ์…˜์—์„œ ๋Œ€์ƒ ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ์Šค๋ƒ…์ƒท ์ƒ์„ฑํ•˜์—ฌ ๋ฐœ์ƒํ•œ ์ผ์ž…๋‹ˆ๋‹ค. ๊ฒฐ๋ก ์ ์œผ๋กœ PostgreSQL์€ Active๋ฅผ ์šฐ์„ ์œผ๋กœ ํ•˜์—ฌ ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์„ IN_PROGRESS๋กœ ๊ฐ„์ฃผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 5์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Invisible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 6์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์€ โ€œIf Status(t_xmin) = COMMITTEDโ€ ์ฆ‰, ์ปค๋ฐ‹๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , โ€œStatus(t_xmax) = ABORTEDโ€ ํ•ด์ œํ•˜๋ฉด T_DELETE๋ฅผ ์ˆ˜ํ–‰ํ•œ ํŠธ๋žœ์žญ์…˜์ด Abort ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ํŠœํ”Œ์€ ์ƒ์„ฑ ์ดํ›„ T_DELETE๋ฅผ ํ–ˆ์ง€๋งŒ ํ•ด๋‹น ๋™์ž‘์ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 6์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Visible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 7์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์€ โ€œIf Status(t_xmin) = COMMITTEDโ€ ์ฆ‰, ์ปค๋ฐ‹๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , t_xmax๊ฐ€ 0์ด๋ฏ€๋กœ ์ƒ์„ฑ ์ดํ›„ T_DELETE ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ํŠœํ”Œ์€ ์ƒ์„ฑ ์ดํ›„ T_DELETEํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 7์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Visible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 8์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ โ€œIf Status(t_xmin) = COMMITTED โˆง Status(t_xmax) = IN_PROGRESSโ€ ์ฆ‰, ํ•ด๋‹น ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์€ ์ปค๋ฐ‹๋˜์—ˆ๊ณ , ํ•ด๋‹น ํŠœํ”Œ์„ UPDATE ๋˜๋Š” DELETE๋ฅผ ํ†ตํ•ด T_DELETEํ•œ ํŠธ๋žœ์žญ์…˜์€ ์•„์ง ์ปค๋ฐ‹๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•ด๋‹น ํŠœํ”Œ์€T_DELETE๋ฅผ ์ˆ˜ํ–‰ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ๋งŒ ๋ณด์—ฌ์ง€์ง€ ์•Š๊ณ (์•„์ง T_DELETE๊ฐ€ COMMIT์ด ์•ˆ๋˜์—ˆ์œผ๋ฏ€๋กœ), ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ๋ณด์—ฌ์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค(ํ•ด๋‹น ํŠœํ”Œ์„ ์ƒ์„ฑํ•œ T_INSERT๋Š” COMMIT๋˜์—ˆ์œผ๋ฏ€๋กœ). Rule 7์€ โ€œt_xmax = current_txidโ€, ์ฆ‰ ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์ด T_DELETE๋ฅผ ์ˆ˜ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 7์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Invisible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 9์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Rule 7๊ณผ ๋‹ฌ๋ฆฌ โ€œt_xmax โ‰  current_txid AND t_xmax โ‰  0โ€ ์ฆ‰, T_DELETE๋ฅผ ์ˆ˜ํ–‰ํ•œ ํŠธ๋žœ์žญ์…˜์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 8์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์„ Visible์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 10์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ โ€œIf Status(t_xmin) = COMMITTEDโ€ ์ฆ‰, ์ƒ์„ฑํ•œ ํŠธ๋žœ์žญ์…˜์€ ์ปค๋ฐ‹๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , โ€œStatus(t_xmax) = COMMITTED โˆง Snapshot(t_xmax) = activeโ€ ํ•ด๋‹น ํŠœํ”Œ์„ T_DELETEํ•œ ํŠธ๋žœ์žญ์…˜์€ ์ปค๋ฐ‹๋˜์—ˆ์œผ๋‚˜ ์•„์ง Active์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” Rule 5์—์„œ ์กฐ๊ธˆ ์ด์ƒํ•œ ์ƒํ™ฉ์— ๋Œ€ํ•ด ์ด๋ฏธ ์„ค๋ช…ํ•˜์˜€์Šต๋‹ˆ๋‹ค. Active ์ƒํƒœ๊ฐ€ ์šฐ์„ ๋˜๋ฏ€๋กœ IN_PROGRESS๋กœ ๊ฐ„์ฃผํ•˜๋ฏ€๋กœ ์•„์ง T_DELETE๊ฐ€ ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 9์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Visible ์ž…๋‹ˆ๋‹ค.
โ€ข
Rule 11์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Rule 9์™€ ๋‹ฌ๋ฆฌ โ€œSnapshot(t_xmax) โ‰  activeโ€ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, T_DELETE๊ฐ€ ๋ฐ˜์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Rule 10์— ํ•ด๋‹นํ•˜๋Š” ํŠœํ”Œ์€ Invisible ์ž…๋‹ˆ๋‹ค.

Isolation Level

Isolation Level์€ ํŠธ๋žœ์žญ์…˜์˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์œผ๋กœ ANSI SQL-92์—์„œ ๋ฐœ์ƒํ•˜๋Š” ํ˜„์ƒ์— ๋”ฐ๋ผ ์ •์˜ํ•œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.
ANSI SQL-92 MS, ANSI] defines Isolation Levels in terms of phenomena.
Reference. Berenson, Hal, et al. "A critique of ANSI SQL isolation levels."ย ACM SIGMOD Record ย 24.2 (1995): 1-10.
SQL-92์—์„œ๋Š” ๋‹ค์Œ 3๊ฐ€์ง€ ํ˜„์ƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ ์ •์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
โ€ข
Dirty Read 1. ํŠธ๋žœ์žญ์…˜ T1์ด ํŠน์ • ๋ฐ์ดํ„ฐ A๋ฅผ B๋กœ ์ˆ˜์ • 2. ํŠธ๋žœ์žญ์…˜ T2๊ฐ€ ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ B๋ฅผ ์กฐํšŒ 3. ํŠธ๋žœ์žญ์…˜ T1์ด ๋กค๋ฐฑ(Rollback)์„ ์ˆ˜ํ–‰ โ‡’ ๋กค๋ฐฑ์ด ์ˆ˜ํ–‰๋˜์–ด ์ปค๋ฐ‹๋œ ์ ์ด ์—†์–ด ์กด์žฌํ•œ ์ ์ด ์—†๋Š” ๋ฐ์ดํ„ฐ B๋ฅผ T2๊ฐ€ ์กฐํšŒ
โ€ข
Non-repeatable Read 1. ํŠธ๋žœ์žญ์…˜ T1์ด ํŠน์ • ๋ฐ์ดํ„ฐ A๋ฅผ ์กฐํšŒ 2. ํŠธ๋žœ์žญ์…˜ T2๊ฐ€ ๋ฐ์ดํ„ฐ A๋ฅผ B๋กœ ์ˆ˜์ •(๋˜๋Š” ์‚ญ์ œ)ํ•˜๊ณ  ์ปค๋ฐ‹ 3. ํŠธ๋žœ์žญ์…˜ T1์ด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ์กฐํšŒํ•˜๋ฉด B(๋˜๋Š” ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋‹ค๋Š” ๊ฒฐ๊ณผ)์„ ์กฐํšŒ โ‡’ ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ T1์—์„œ ๊ฐ™์€ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์กฐํšŒ
โ€ข
Phantom Read 1. ํŠธ๋žœ์žญ์…˜ T1์ด ํŠน์ • ์ฟผ๋ฆฌ๋กœ READํ•˜์—ฌ SET1์„ ๊ฒฐ๊ณผ๋กœ ์กฐํšŒ 2. ํŠธ๋žœ์žญ์…˜ T2๊ฐ€ ํ•ด๋‹น ์ฟผ๋ฆฌ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ฐ์ดํ„ฐ A๋ฅผ ์ถ”๊ฐ€ 3. ํŠธ๋žœ์žญ์…˜ T1์ด ํ•ด๋‹น ์ฟผ๋ฆฌ๋กœ ๋‹ค์‹œ READํ•˜์—ฌ A๊ฐ€ ํฌํ•จ๋œ SET2๋ฅผ ๊ฒฐ๊ณผ ์กฐํšŒ โ‡’ ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ T1์—์„œ ๊ฐ™์€ ์ฟผ๋ฆฌ๋กœ ์กฐํšŒํ•œ ๊ฒฐ๊ณผ์ธ SET1๊ณผ SET2๊ฐ€ ๋ถˆ์ผ์น˜
SQL-92์—์„œ๋Š” ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ 3๊ฐ€์ง€ ํ˜„์ƒ์˜ ๋ฐœ์ƒ ์—ฌ๋ถ€๋ฅผ ๊ธฐ์ค€์œผ๋กœ 4๋‹จ๊ณ„์˜ ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ ์ •์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Isolation Level
Dirty Read
Non-repeatable Read
Phantom Read
Read uncommitted
Possible
Possible
Possible
Read committed
Not possible
Possible
Possible
Repeatable read
Not possible
Not possible
Possible
Serializable
Not possible
Not possible
Not possible
* ์œ„์˜ ์ •์˜๋Š” ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์˜ ๊ฐœ๋…์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ์œ„ํ•ด ์›์ „์„ ์ธ์šฉํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ ๋ฒค๋” ๋ณ„๋กœ ์ •์˜ํ•˜๋Š” ํ˜„์ƒ๊ณผ ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์€ ์ƒ์ดํ•˜๋ฏ€๋กœ ์ฐธ๊ณ  ๋ฐ”๋ž๋‹ˆ๋‹ค.
PostgreSQL์—์„œ ์ •์˜ํ•˜๋Š” ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์€ ๋‹ค์Œ ํ‘œ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Isolation Level
Dirty Read
Non-repeatable Read
Phantom Read
Serialization Anomaly
Read uncommitted
Allowed, but not in PG
Possible
Possible
Possible
Read committed
Not possible
Possible
Possible
Possible
Repeatable read
Not possible
Not possible
Allowed, but not in PG
Possible
Serializable
Not possible
Not possible
Not possible
Not possible
PostgreSQL์—์„œ๋Š” ํŠธ๋žœ์žญ์…˜ T1๊ณผ T2๊ฐ€ ์žˆ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, Visibility Rule 5์— ์˜ํ•ด T2์—์„œ ์กฐํšŒํ•œ ์Šค๋ƒ…์ƒท์—์„œ ๋ณด์—ฌ์ง€๋Š” T1์˜ Active ์—ฌ๋ถ€๊ฐ€ T1์˜ ํŠธ๋žœ์žญ์…˜ ์ƒํƒœ์— ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํŠธ๋žœ์žญ์…˜ ์ƒํƒœ๊ฐ€ COMMITTED๋ผ ํ•˜๋”๋ผ๋„ ์กฐํšŒํ•œ ์Šค๋ƒ…์ƒท์ด Activeํ•˜๋‹ค๋ฉด IN_PROGRESS๋กœ ๊ฐ„์ฃผํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ทœ์น™์— ์˜ํ•ด PostgreSQL์€ Read uncommitted์˜ Dirty Read, Repeatable read์˜ Phantom Read ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Lost Update (Write-Write Conflict)

Lost Update ํ˜„์ƒ์€ ๋‘ ๊ฐœ์˜ ํŠธ๋žœ์žญ์…˜์—์„œ ๋™์‹œ์— UPDATE๋ฅผ ์ˆ˜ํ–‰ํ•  ๊ฒฝ์šฐ ์ฒซ๋ฒˆ์งธ ํŠธ๋žœ์žญ์…˜์˜ UPDATE๊ฐ€ ๋ˆ„๋ฝ๋˜๋Š” ํ˜„์ƒ์œผ๋กœ ์œ„์—์„œ ์ธ์šฉํ–ˆ๋˜ โ€œA critique of ANSI SQL isolation levelsโ€์—์„œ ์–ธ๊ธ‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
Reference. Berenson, Hal, et al. "A critique of ANSI SQL isolation levels."ย ACM SIGMOD Record ย 24.2 (1995): 1-10.
PostgreSQL์—์„œ๋Š” Repeatable Read์™€ Serializable ์ˆ˜์ค€์—์„œ Lost Update ํ˜„์ƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
ํŠธ๋žœ์žญ์…˜ T2์—์„œ UPDATE ํ•  ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๊ฐ€ ํŠธ๋žœ์žญ์…˜ T1์— ์˜ํ•ด UPDATE๊ฐ€ ์ง„ํ–‰ ์ค‘์ด๋ฉด T1์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
โ€ข
๋งŒ์•ฝ ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜์—ˆ๋‹ค๋ฉด,
โ—ฆ
REPEATABLE READ, SERIALIZABLE์ด๋ฉด T2๋ฅผ Abort ํ•ฉ๋‹ˆ๋‹ค.
โ—ฆ
READ COMMITTED์ด๋ฉด UPDATE๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
Repeatable Read, Serializable ์ˆ˜์ค€์—์„œ๋Š” ๋‘๋ฒˆ์งธ ํŠธ๋žœ์žญ์…˜์„ ์•„์˜ˆ Abort ํ•ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ๋ฒˆ์งธ ํŠธ๋žœ์žญ์…˜์˜ UPDATE๊ฐ€ ๋ˆ„๋ฝ๋˜๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ง€๊ธˆ๊นŒ์ง€ PostgreSQL์˜ Concurrency Control์— ๊ด€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค
โ€˜PostgreSQL์˜ Vacuumโ€™๋ฅผ ๋ฐ”๋กœ ์ด์–ด์„œ ํ™•์ธํ•ด๋ณด์„ธ์š”!

์ž์œ ๋กญ๊ฒŒ ๋Œ“๊ธ€์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”