๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์—‘์…ˆ ๊ฒฝ์Ÿ๋ ฅ/DB ์ธ์‚ฌ์ด๋“œ

DB ์ธ์‚ฌ์ด๋“œ | PostgreSQL Vacuum - 3. Age

by EXEM 2022. 4. 29.

๐Ÿ“ข ๋ณธ ๋ฌธ์„œ์—์„œ๋Š” XID์˜ ์—ฐ์žฅ์„ ์ƒ์— ์žˆ๋Š” Age์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. โ‘ Age์˜ ๊ฐœ๋…๊ณผ ๋„์ž… ๋ฐฐ๊ฒฝ์„ ์šฐ์„  ํ™•์ธํ•œ ํ›„, โ‘กTable ๋ฐ Row์—์„œ ์‚ฌ์šฉ๋˜๋Š” Age์˜ ์˜๋ฏธ์™€ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Age ๋ž€?

Age = Current XID - ์ƒ์„ฑ์‹œ์ ์˜ XID

์•ž์„œ Data Freezing๊ณผ์ •์„ ์„ค๋ช…ํ•˜๋ฉฐ “Current XID - ์ƒ์„ฑ(์ž…๋ ฅ) ์‹œ์ ์˜ XID” ๊ฐ’์ด 21์–ต์„ ์ดˆ๊ณผํ•˜๊ธฐ ์ „์— Frozen XID๋กœ ๋ณ€๊ฒฝ๋ผ์•ผ XID Wraparound ์ƒํ™ฉ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ด์•ผ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ฒ˜๋Ÿผ Data Freezing ๋Œ€์ƒ์„ ์„ ์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” XID๊ฐ’ ๊ทธ ์ž์ฒด๋ณด๋‹ค๋Š” ์ž…๋ ฅ(์ƒ์„ฑ) ํ›„ ์–ผ๋งˆ๋‚˜ ์˜ค๋ž˜๋˜์—ˆ๋Š”์ง€ ์ธก์ •ํ•  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ด์กŒ์œผ๋ฉฐ ์ด๋ฅผ ์œ„ํ•œ ๊ฐœ๋…์œผ๋กœ Age๊ฐ€ ๋„์ž…๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Age์˜ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Age ์ธก์ •์˜ ๋Œ€์ƒ์€ DB / Table / Row์ด๋‹ค.
  • Object ์ƒ์„ฑ ์‹œ์ ์˜ Age๋Š” 1์ด๋‹ค.
  • Row ์ž…๋ ฅ ์‹œ์ ์˜ Age๋Š” 1์ด๋‹ค.
  • ํŠธ๋žœ์žญ์…˜ ๋ฐœ์ƒ ์‹œ ๊ฐ๊ฐ์˜ Age๋Š” ์ฆ๊ฐ€ํ•œ๋‹ค.
  • Object์˜ Age๋Š” Row์˜ Age์™€ ๊ฐ™๊ฑฐ๋‚˜ ํฌ๋‹ค.
  • Age๊ฐ€ ํฐ Object ๋ฐ Row๋Š” Vacuum์˜ ๋Œ€์ƒ์ด ๋œ๋‹ค.
  • Vacuum ์ˆ˜ํ–‰ ํ›„ Age๋Š” ๋‚ฎ์•„์ง„๋‹ค.

Table๊ณผ Row์˜ Age๋Š” age ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ณ„์‚ฐ์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ์ด๋ ‡๊ฒŒ ๊ณ„์‚ฐ๋˜๋Š” Age๋Š” Vacuum์˜ ๋Œ€์ƒ์„ ์„ ์ •ํ•˜๊ฑฐ๋‚˜ ๋‚ด๋ถ€์ ์ธ ๋™์ž‘ ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•˜๋Š”๋ฐ ๊ธฐ์ค€์  ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. Age๋ฅผ ์ด์šฉํ•œ ๋‚ด๋ถ€ ๋™์ž‘ ๊ณผ์ •์— ๊ด€ํ•ด์„œ๋Š” ์ดํ›„ Manual Vacuum๊ณผ์ •์„ ํ†ตํ•ด ๋ณด๋‹ค ์ž์„ธํžˆ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

Table๊ณผ Row์˜ Age

Age๊ฐœ๋…์€ XID์™€ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Age ์ž์ฒด๊ฐ€ ์ƒ์„ฑ ์‹œ์ ์˜ XID์™€ Current XID์˜ ์ฐจ์ด๋ฅผ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ, ๊ฐ™์€ ์ด์œ ๋กœ Age๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ณณ ์—ญ์‹œ XID์™€ ๋™์ผํ•œ Database, Table, Row์ž…๋‹ˆ๋‹ค. ์ด ์ค‘ Row์˜ Age์— ๋Œ€ํ•ด ๋จผ์ € ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Row Age

--Row(Tuple) Age
insert into age_table values(1);
insert into age_table values(2);
insert into age_table values(3);

select age(xmin),
    txid_current() as current_xid,
    xmin,
    c1 
from age_Table;

age|current_xid|xmin    |c1|
---+-----------+--------+--+
  3|   19314384|19314381| 1|
  2|   19314384|19314382| 2|
  1|   19314384|19314383| 3|

Row์˜ Age๋Š” XMIN์„ ์ด์šฉํ•˜์—ฌ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ์˜ˆ์ œ์—์„œ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ ์‹œ์ ์˜ XID๊ฐ€ XMIN์œผ๋กœ ์„ค์ •๋˜๋Š”๋ฐ, XMIN์— Ageํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜๋ฉด Row์˜ Age๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

"Row" ๊ทธ ์ž์ฒด๋Š” Data Freezing์˜ ๋Œ€์ƒ์ด์ง€๋งŒ "Row์˜ Age"๋Š” Data Freezing์˜ ๊ธฐ์ค€์ด ๋ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ž…๋ ฅ ํ›„ Transaction์ด ๋ฐœ์ƒํ• ์ˆ˜๋ก Row์˜ Age ์—ญ์‹œ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋งˆ๋ จ์ด๋ฉฐ, Row์˜ Age๊ฐ€ VACUUM_FREEZE_MIN_AGE ์ˆ˜์น˜์— ๋„๋‹ฌํ•˜๋ฉด Data Freezing์˜ ๋Œ€์ƒ์ด ๋ฉ๋‹ˆ๋‹ค. ์ดํ›„ Vacuum์ž‘์—… ์‹œ ์‹ค์ œ Data Freezing์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ vacuum_freeze_min_age
Vacuum์ด Freeze ํ•  Row์˜ ์ตœ์†Œ Age์ด๋ฉฐ, ๊ธฐ๋ณธ๊ฐ’์€ 5์ฒœ๋งŒ(50,000,000)์ž…๋‹ˆ๋‹ค.

 

์ด๋Ÿฌํ•œ Data Freezing์ž‘์—…์€ 9.4 ๋ฒ„์ „ ์ด์ „๊นŒ์ง€๋Š” ์‹ค์ œ XMIN๊ฐ’์„ Frozen XID๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ 9.4 ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” XMIN์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๋Œ€์‹  t_infomask์˜ 10๋ฒˆ์งธ Bit๊ฐ’์„ 1๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

VACUUM FREEZE๋ช…๋ น์„ ํ†ตํ•ด ๊ฐ•์ œ๋กœ Data Freezing์„ ๋ฐœ์ƒ์‹œํ‚จ ํ›„ ๋ณ€ํ™”๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ช…๋ น์–ด ์ˆ˜ํ–‰ ํ›„ XMIN๊ฐ’์˜ ๋ณ€๊ฒฝ์€ ์—†์ง€๋งŒ t_infomask๊ฐ’์€ ๋ณ€๊ฒฝ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

select * from heap_page_items(get_raw_page('age_table', 0))

lp|lp_off|lp_flags|lp_len|**t_xmin**  |t_xmax|t_field3|t_ctid|t_infomask2|**t_infomask**|t_hoff|t_bits|t_oid|t_data|
--+------+--------+------+--------+------+--------+------+-----------+----------+------+------+-----+------+
 1|  8160|       1|    28|**19314381**|0     |       0|(0,1) |          1|      **2304**|    24|      |     |      |
 2|  8128|       1|    28|**19314382**|0     |       0|(0,2) |          1|      **2304**|    24|      |     |      |
 3|  8096|       1|    28|**19314383**|0     |       0|(0,3) |          1|      **2304**|    24|      |     |      |

vacuum freeze age_table;

select * from heap_page_items(get_raw_page('age_table', 0))

 lp|lp_off|lp_flags|lp_len|**t_xmin**  |t_xmax|t_field3|t_ctid|t_infomask2|**t_infomask**|t_hoff|t_bits|t_oid|t_data|
--+------+--------+------+--------+------+--------+------+-----------+----------+------+------+-----+------+
 1|  8160|       1|    28|**19314381**|0     |       0|(0,1) |          1|      **2816**|    24|      |     |      |
 2|  8128|       1|    28|**19314382**|0     |       0|(0,2) |          1|      **2816**|    24|      |     |      |
 3|  8096|       1|    28|**19314383**|0     |       0|(0,3) |          1|      **2816**|    24|      |     |      |
๐Ÿ“Œ ์œ„ ์˜ˆ์ œ๋Š” pageinspect Extension์„ ์„ค์น˜ํ•ด์•ผ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
[PostgreSQL: Documentation: 14: F.23. pageinspect]

 

ํ•ด๋‹น t_infomask๊ฐ’์„ Bit๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด 10๋ฒˆ์งธ Bit๊ฐ€ 0์—์„œ 1๋กœ ๋ณ€๊ฒฝ๋˜๋ฉด์„œ ์‹ค์ œ Data Freezing์ด ๋ฐœ์ƒํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

select  2304::bit(16) as before, 2816::bit(16) as after

before          |after           |
----------------+----------------+
0000100100000000|0000101100000000|

Table Age

์ด๋ฒˆ์—๋Š” Table์˜ Age์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Table์˜ Age๋Š” pg_class.relfrozenxid๋ฅผ ์ด์šฉํ•ด ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

--Object(Table) Age
create table age_table (c1 integer);

select age(relfrozenxid) as age, 
    txid_current() as current_xid, 
    relfrozenxid  as created_xid
from pg_class where relname ='age_table';

age|current_xid|created_xid|
---+-----------+-----------+
  1|   19314370|19314369   |

Object์˜ Age๋Š” Row์˜ Age์™€ ๊ฐ™๊ฑฐ๋‚˜ ํฌ๋‹ค. (์˜ค๋ž˜๋๋‹ค)

Row์™€ ๋‹ฌ๋ฆฌ Table์€ Freezing ๋Œ€์ƒ์ด ์•„๋‹ˆ๋ฉฐ ๋Œ€์ƒ์ผ ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, Freezing์˜ ๋Œ€์ƒ๋„ ์•„๋‹Œ Table์˜ Age๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒ ์˜๋ฌธ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์œ„์™€ ๊ฐ™์€ Age์˜ ํŠน์„ฑ์œผ๋กœ ์ธํ•ด, Table์˜ Age๋Š” Row๋“ค์˜ Age๋ฅผ ๋Œ€ํ‘œํ•˜๋Š” ์—ญํ• ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ด๋Š” Data Freezing์„ ํ•„์š”๋กœ ํ•˜๋Š” Row์˜ ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ์†์‰ฝ๊ฒŒ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ค€์œผ๋กœ์„œ ๊ทธ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค, Table์˜ Age๊ณ„์‚ฐ์— ์‚ฌ์šฉ๋˜๋Š” relfrozenxid ์—ญ์‹œ ํŠน์ • ์กฐ๊ฑด ๋งŒ์กฑ ์‹œ ๊ทธ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋กœ ์ธํ•ด Table์˜ Age ์—ญ์‹œ ๋‚ฎ์•„์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ์˜ ์กฐ๊ฑด์ด๋ž€ ์ „์ฒด ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ Data Freezing ํ•„์š” ์—ฌ๋ถ€๋ฅผ ๋ชจ๋‘ ํ™•์ธํ•œ ์‹œ์ ์„ ์ผ์ปซ๋Š”๋ฐ, ํ•ด๋‹น ๋‚ด์šฉ์˜ ์ดํ•ด๋ฅผ ์œ„ํ•ด์„œ๋Š” Eager Mode์˜ Vacuum ๋™์ž‘์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ, ์ดํ›„ Manual Vacuum ๊ณผ์ •์„ ํ†ตํ•ด ๋‹ค์‹œ ํ•œ๋ฒˆ ์–ธ๊ธ‰ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ง€๊ธˆ๊นŒ์ง€ PostgreSQL์˜ MVCC๋ชจ๋ธ์„ ์‹œ์ž‘์œผ๋กœ Transaction ID, Age ๋“ฑ XID๊ด€๋ จ ๋‚ด์šฉ์„ ๋‹ค๋ค˜๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฌธ์„œ์—์„œ๋Š” Vacuum์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๊ผญ ํ•„์š”ํ•œ Visibility Map์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

๊ธฐํš ๋ฐ ๊ธ€ | ๊ธฐ์ˆ ๊ธฐํšํŒ€

์ด๋ฏธ์ง€ ์ œ์ž‘ | ๋””์ž์ธ๊ทธ๋ฃน ์ด๋ฏผ์„

 

 

 

๋Œ“๊ธ€0