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โ๋ฅผ ๋ฐ๋ก ์ด์ด์ ํ์ธํด๋ณด์ธ์!