๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๊ณต๋ถํ๋ค ๋ณด๋ฉด ๋์์ฑ ์ ์ด์์ ๋น๊ด์ ๋ฝ๊ณผ ๋๊ด์ ๋ฝ ๋ง๊ณ ๋ MVCC (Multi-Version Concurrency Control) ๋ผ๋ ๊ฐ๋
์ ์ ํ๊ฒ ๋ฉ๋๋ค. PostgreSQL, MySQL, Oracle ๊ฐ์ ๋๋ถ๋ถ์ ํ๋์ ์ธ RDBMS๋ MVCC ๊ธฐ๋ฐ ๋์์ฑ ์ ์ด๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
์ค๋์ MVCC๊ฐ ์ ํํ ๋ญ์ง, Lock ๋ฐฉ์๊ณผ ๋ฌด์์ด ๋ค๋ฅธ์ง, ๋ด๋ถ ๋์ ์๋ฆฌ์ ๋ํด์๋ ํ์ตํด ๋ณด์์ต๋๋ค. ๋์ ๊ธฐ์ค์ PostgreSQL ๋ก ํ์ตํ์์ต๋๋ค. ๊ฐ DB ๋ง๋ค MVCC ๊ธฐ์ ์ ๋ฐฉ์์ด ์ ์์๋ฅผ ๋ณด์๊ณ MYSQL๋ ์ ๋ ๊ฒ ๋์ํ๊ตฌ๋ ์๊ฐํ์๋ฉด ์ ๋ฉ๋๋ค. ํฐ ํ์์ ๋ชฉํ์ ๊ฐ๋
์ ๊ฐ์ง๋ง ๊ทธ๊ฑธ ๊ตฌํํ ๋ฐฉ์์ DB ๋ง๋ค ๊ฐ๊ฐ ๋ค๋ฆ
๋๋ค.
1. MVCC๋ ๋ฌด์์ธ๊ฐ
MVCC (Multi-Version Concurrency Control) ๋ ์ฌ๋ฌ ํธ๋์ญ์
์ด ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์์ ํ ์ ์๋๋ก ํ๊ธฐ ์ํ ๋์์ฑ ์ ์ด ๋ฐฉ์์
๋๋ค.
ํต์ฌ ์์ด๋์ด๋ ๋งค์ฐ ๋จ์ํฉ๋๋ค.
๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋ ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๋ฎ์ด์ฐ์ง ์๊ณ ์๋ก์ด ๋ฒ์ ์ ์์ฑํ๋ค.
์ ํต์ ์ธ ๋ฐฉ์์์๋ ํ๋์ ๋ฐ์ดํฐ๋ ํ๋์ ๊ฐ๋ง ์กด์ฌํฉ๋๋ค.
row(id=1)
value = 10
ํ์ง๋ง MVCC์์๋ ํ๋์ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฌ ๋ฒ์ ์ ๊ฐ์ง ์ ์์ต๋๋ค.
row(id=1)
version1 → value = 10
version2 → value = 20
version3 → value = 30
๊ฐ ํธ๋์ญ์
์ ์์ ์ด ๋ณผ ์ ์๋ ๋ฒ์ ๋ง ์ฝ๊ฒ ๋ฉ๋๋ค.
์ด ๊ตฌ์กฐ ๋๋ถ์ ์ฌ๋ฌ ํธ๋์ญ์
์ด ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์์ ํ๋๋ผ๋ ์๋ก ์ถฉ๋ํ์ง ์๊ณ ๋์ํ ์ ์์ต๋๋ค.
2. ์ MVCC๊ฐ ํ์ํ ๊น
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ฅ ํํ๊ฒ ๋ฐ์ํ๋ ๋ฌธ์ ๋ ์ฝ๊ธฐ์ ์ฐ๊ธฐ์ ์ถฉ๋์
๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์ ์ํฉ์ ์๊ฐํด๋ณด๊ฒ ์ต๋๋ค.
Transaction A
SELECT balance FROM account WHERE id = 1; // Shared Lock ์ก์
Transaction B
UPDATE account SET balance = 200 WHERE id = 1; //Exclusive Lock ์ก์
Transaction A๋ id ๊ฐ 1์ธ row ์ balance ๋ฅผ ์ฝ์ผ๋ ค๊ณ ํ๊ณ ์๊ณ , Transaction B ๋ id ๊ฐ 1์ธ row ์ balance ๊ฐ์ 200์ผ๋ก ์์ ํ๋ ค๊ณ ํฉ๋๋ค.
์ ํต์ ์ธ Lock ๊ธฐ๋ฐ DB์์๋ ์ด๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
Transaction A๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ผ๋ฉด Shared Lock์ ์ก์ต๋๋ค.
Transaction B๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ค๋ฉด Exclusive Lock์ด ํ์ํฉ๋๋ค.
ํ์ง๋ง Shared Lock๊ณผ Exclusive Lock์ ์๋ก ์ถฉ๋ํฉ๋๋ค. ๊ทธ๋์ Transaction B๋ ๋๊ธฐ ์ํ์ ๋ค์ด๊ฐ๋๋ค.
"์ฝ๊ธฐ → ์ฐ๊ธฐ ๋๊ธฐ ๋ฐ์"
์ด ๊ตฌ์กฐ์์๋ ํธ๋์ญ์
์ด ๋ง์์ง์๋ก Lock ๋๊ธฐ์ ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
MVCC๋ ์ด ๋ฌธ์ ๋ฅผ ๋ฒ์ ๊ด๋ฆฌ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํฉ๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์ ์ํฉ์ ๋ณด๊ฒ ์ต๋๋ค.
์ด๊ธฐ ์ํ
balance = 100
๊ฐ๊ฐ์ ํธ๋์ญ์ ์์
Transaction A ์์
balance = 100 ์ฝ์
Transaction B
balance = 200 ์
๋ฐ์ดํธ
DB ๋ด๋ถ
version1 balance = 100
version2 balance = 200
์ด๋ ๊ฒ ๋๋ฉด Transaction A๋ version1์ ์ฝ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ๋ฆฝ๋๊ฒ Transaction B๋ version2๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก
Transaction A → 100
Transaction B → 200
์ฝ๊ธฐ์ ์ฐ๊ธฐ๊ฐ ์๋ก ๋ง์ง ์๊ฒ ๋ฉ๋๋ค.
3. MVCC ๋ด๋ถ ๋์ ๊ตฌ์กฐ
๋๋ถ๋ถ์ MVCC ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ฐ row์ ํธ๋์ญ์
๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.
PostgreSQL์ ์๋ก ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค.
row
โ xmin (์์ฑ ํธ๋์ญ์
ID)
โ xmax (์ญ์ ํธ๋์ญ์
ID)
โ data
xmin ์ ์ด row๋ฅผ ์์ฑํ ํธ๋์ญ์ ๊ทธ๋ฆฌ๊ณ xmax = ์ด row๋ฅผ ์ญ์ ํ ํธ๋์ญ์ ์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์๋ ๊ฐ์ ์ด๋ฏธ์ง์ฒ๋ผ ํ์๋ผ์ธ ์์ผ๋ก ์ฐ์ฐ์ ์งํํ๋ค๊ณ ํ๊ฒ ์ต๋๋ค.

1๏ธโฃ ์ฒซ ๋ฒ์งธ ํธ๋์ญ์ — ๋ฐ์ดํฐ ์์ฑ
์ผ์ชฝ์์ ์ฒซ ๋ฒ์งธ ํธ๋์ญ์ ์ด ์์๋ฉ๋๋ค.
BEGIN
INSERT INTO numbers (1)
INSERT INTO numbers (2)
COMMIT
์ด ์์ ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์๋ ๋ ๊ฐ์ row๊ฐ ์์ฑ๋ฉ๋๋ค.
MVCC์์๋ row์ ๋ค์๊ณผ ๊ฐ์ ๋ฉํ๋ฐ์ดํฐ๊ฐ ๊ธฐ๋ก๋ฉ๋๋ค.
row(value=1)
xmin = cur_tx1
xmax = null
row(value=2)
xmin = cur_tx1
xmax = null
cur_tx1 ์ด ๊ฐ๊ฐ์ row๋ฅผ ์์ฑํ์ผ๋ฏ๋ก ๊ฐ๊ฐ์ ๋ฐ์ดํฐ์ xmin ๊ฐ์ cur_ tx1์ ๋๋ค.
2๏ธโฃ ๋ ๋ฒ์งธ ํธ๋์ญ์ — Snapshot ์์ฑ
์ค๋ฅธ์ชฝ์์ ์๋ก์ด ํธ๋์ญ์ ์ด ์์๋ฉ๋๋ค.
BEGIN
์ด ์๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ snapshot์ ์์ฑํฉ๋๋ค.
Snapshot์ ๊ฐ๋จํ ๋งํ๋ฉด "ํธ๋์ญ์
์ด ์์๋ ์์ ์ ๋ฐ์ดํฐ ์ํ" ์
๋๋ค.
์ด snapshot์๋ ๋ค์ ์ ๋ณด๊ฐ ํฌํจ๋ฉ๋๋ค.
- ํ์ฌ ํธ๋์ญ์ ID
- ํ์ฑ ํธ๋์ญ์ ๋ชฉ๋ก
- commit ๋ ํธ๋์ญ์
์ด snapshot ๊ธฐ์ค์ผ๋ก ์ด๋ค row๋ฅผ ๋ณผ ์ ์๋์ง๊ฐ ๊ฒฐ์ ๋ฉ๋๋ค.
cur_trx2 ๊ฐ BEGIN ๋๋ ์์ ์๋ cur_trx1์ด ์ปค๋ฐ๋์ง ์์ ์ํ์ ๋๋ค. ๋ฐ๋ผ์ cur_trx2 ๊ฐ BEGIN ๋์ ๋ ์ค๋ ์ท์ value๊ฐ 1์ธ row๊ฐ ์๋ฌด๊ฒ๋ ์๋ ์ค๋ ์ท์ด๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ COMMIT ํ์ ๋๋ ์กฐํ ๊ฒฐ๊ณผ๊ฐ 0์ด ๋์ค๊ฒ ๋ฉ๋๋ค.
3๏ธโฃ ์ธ ๋ฒ์งธ ํธ๋์ญ์ SELECT ์คํ
cur_trx3 ํธ๋์ญ์ ์ด ๋ค์ ์ฟผ๋ฆฌ๋ฅผ ์คํํฉ๋๋ค.
BEGIN
-- ๋ค๋ฅธ ์ฟผ๋ฆฌ
SELECT * FROM numbers WHERE value = 1
cur_trx3 ํธ๋์ญ์ ์ด BEGIN ํ์ ์์ ์ ์ค๋ ์ท์ ๋จ๊ธฐ๋ฏ๋ก cur_trx2 ์ cur_trx1์ด ์ปค๋ฐ๋ ์์ ์ ๋๋ค.
์ค๋ ์ท์ row๋ value๊ฐ 1์ธ row ์ value๊ฐ 2 ์ธ row 2๊ฐ๊ฐ ์กด์ฌํ๊ฒ ๋ฉ๋๋ค. ์ค๋ ์ท์ cur_trx4์ ๋ด์ฉ์ ๋ฐ์๋์ด ์์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ์ด ์์ ์์๋ ์ญ์ ๊ฐ ๋ฐ์ํ์ง ์์๊ธฐ ๋๋ฌธ์ value๊ฐ 1์ธ row๊ฐ ๋ณด์ ๋๋ค.
trx3 ํธ๋์ญ์
์ snapshot์์๋ DELETE ํธ๋์ญ์
(tx4) ์ด ์์ง ์กด์ฌํ์ง ์๋ ๊ฒ์ผ๋ก ๋ณด์ด๊ธฐ ๋๋ฌธ์
๋๋ค.
MVCC์์๋ ํธ๋์ญ์
๋ง๋ค ์๋ก ๋ค๋ฅธ "๋ฐ์ดํฐ ์ธ๊ณ"๋ฅผ ๋ณด๊ณ ์์ต๋๋ค.(๋ฒ์ ๋)
4๏ธโฃ ๋ค ๋ฒ์งธ ํธ๋์ญ์ ์์ DELETE ๋ฐ์
์ผ์ชฝ์์ ์๋ก์ด ํธ๋์ญ์ ์ด ์์๋ฉ๋๋ค.
BEGIN
DELETE FROM numbers WHERE value = 1
COMMIT
MVCC์์๋ DELETE๊ฐ ์ค์ ๋ก row๋ฅผ ์ง์ฐ์ง ์์ต๋๋ค.
๋์ row์ xmax๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
์ฆ ๋ด๋ถ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
row(value=1)
xmin = tx1
xmax = tx4
์ด ์๋ฏธ๋ "tx4 ์ดํ์๋ ์ด row๊ฐ ๋ณด์ด์ง ์๋๋ค" ์
๋๋ค.
ํ์ง๋ง ์ค์ํ ์ ์ด ์์ต๋๋ค. ๋ฌผ๋ฆฌ์ ์ผ๋ก๋ row๊ฐ ์์ง ์กด์ฌํฉ๋๋ค.
5๏ธโฃ ๋ค์ฏ ๋ฒ์งธ ํธ๋์ญ์ SELECT ์คํ
์ด์ ๋ง์ง๋ง ์ค๋ฅธ์ชฝ cur_trx5 ํธ๋์ญ์
์ ๋ณด๊ฒ ์ต๋๋ค. ์๋ก์ด ํธ๋์ญ์
์ ์๋ก์ด snapshot์ ์์ฑํฉ๋๋ค.
์ด snapshot์์๋ ์ด๋ฏธ DELETE๊ฐ ๋ฐ์๋์ด ์์ต๋๋ค.
๊ทธ๋์ ๊ฒฐ๊ณผ๋ 0 rows๊ฐ ๋ฉ๋๋ค.
4. MVCC์์ SELECT๋ ์ด๋ป๊ฒ ๋์ํ ๊น (Snapshot Read)
MVCC์์๋ ํธ๋์ญ์
์ด ์์๋ ๋ snapshot์ด ์์ฑ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด Transaction A๊ฐ ๋ค์ ์์ ์ ์์ํ๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค.
Transaction A ์์ (txid = 150)
์ด ํธ๋์ญ์ ์ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ row๋ง ๋ณผ ์ ์์ต๋๋ค.
xmin <= 150
xmax > 150 OR xmax = null
์ฆ Transaction A๋ ์์ ์ด ์์๋ ์์ ์ ๋ฐ์ดํฐ ์ํ๋ง ๋ณด๊ฒ ๋ฉ๋๋ค.
๊ทธ๋์ ๊ฐ์ ๋ฐ์ดํฐ๋ผ๋ ํธ๋์ญ์
๋ง๋ค ๋ค๋ฅธ ๊ฐ์ ๋ณผ ์ ์์ต๋๋ค.
5. MVCC์์ UPDATE
MVCC์์ UPDATE ๋ ์กฐ๊ธ ํน์ดํ๊ฒ ๋์ํฉ๋๋ค. UPDATE๊ฐ ๋ฐ์ํ๋ฉด ๊ธฐ์กด row์ xmax๊ฐ ์ค์ ๋๊ณ , ์๋ก์ด row๊ฐ ์์ฑ๋๋ฉด์ ๊ทธ row์ xmin์ด ์ค์ ๋ฉ๋๋ค.
์ฆ, UPDATE๋ ์ค์ ๋ก๋ “DELETE + INSERT”์ฒ๋ผ ๋์ํ๊ฒ ๋ฉ๋๋ค.
1๏ธโฃ UPDATE ์ ์ํ
์๋ฅผ ๋ค์ด ๋ค์ row๊ฐ ์๋ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
value = 10
๋ด๋ถ tuple ๋ฉํ๋ฐ์ดํฐ๋ ์ด๋ ๊ฒ ๋ฉ๋๋ค.
row version1
xmin = 100
xmax = null
value = 10
- xmin = 100 → ํธ๋์ญ์ 100์ด ์ด row๋ฅผ ์์ฑ
- xmax = null → ์์ง ์ญ์ ๋์ง ์์
2๏ธโฃ UPDATE ๋ฐ์
์ด์ ํธ๋์ญ์ 200์ด ํด๋น ROW์ UPDATE๋ฅผ ์คํํ๊ฒ ๋ฉ๋๋ค.
UPDATE numbers SET value = 20 WHERE value = 10;
์ด๋ ๊ฒ ๋๋ฉด ๊ธฐ์กด row์ ๊ฐ์ ์ง์ ์์ ํ์ง ์๊ณ , ๋์ ๋ด๋ถ์ ์ผ๋ก ์ด๋ ๊ฒ ๋ณํ๊ฒ ๋ฉ๋๋ค.
- ๊ธฐ์กด row
row version1
xmin = 100
xmax = 200
value = 10
- ์๋ก์ด ROW ์์ฑ
row version2
xmin = 200
xmax = null
value = 20
์ฆ, "old row → ์ญ์ ํ์", "new row → ์ ๋ฒ์ " ์ ๊ฐ๊ฒ ๋ฉ๋๋ค.
๋ง์ฝ ํธ๋์ญ์ 100 ๊ณผ ํธ๋์ญ์ 200 ์ฌ์ด์ ํธ๋์ญ์ 150์์ ๋ค์๊ณผ ๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ค๋ฉด,
xmin=100 → ๋ณด์
xmax=200 → ์์ง ๋ฏธ๋
value ๋ 10์ด ๋๊ฒ ๋ฉ๋๋ค.
ํธ๋์ญ์ 300์ xmin=200 → ๋ณด์ด๋ฏ๋ก value=20 ์ ๋ณด๊ฒ ๋ฉ๋๋ค.
๋ง๋ฌด๋ฆฌ
๊ทธ๋ฆผ์ ํตํด ์ดํด๋ณธ MVCC์ ํต์ฌ์ ๋ค์ ๋ ๊ฐ์ง์
๋๋ค.
1๏ธโฃ ํธ๋์ญ์
๋ง๋ค ์๋ก ๋ค๋ฅธ Snapshot์ ๋ณธ๋ค
Transaction A → ๋ณด์
Transaction B → ์ ๋ณด์
2๏ธโฃ DELETE๋ ์ค์ ์ญ์ ๊ฐ ์๋๋ค
MVCC์์ DELETE, UPDATE ๋ ์ค์ ๋ก row๋ฅผ ์ง์ฐ์ง ์์ต๋๋ค. ๋์ ๊ฐ์ row๋ผ๋ ๋ค๋ฅธ ๋ฒ์ ์ ๋ณด๊ณ ์์ต๋๋ค.
์ด๋ฅผ ํตํด ์ฐ๊ธฐ๋ฝ์ด ๊ฑธ๋ฆฐ ROW์์๋ ์ฝ๊ธฐ๊ฐ ๊ฐ๋ฅํด์ง๊ณ , ์ฌ๋ฌ ํธ๋์ญ์ ์ด ํ ROW ์ ๊ฒฝํฉํ๋ ์ํฉ์์๋ ๋ณด๋ค ์กฐ๊ธ๋ ์ฑ๋ฅ ์ข๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ง์ํ ์ ์๊ฒ ๋ฉ๋๋ค.
๋๊ธ