[PostgreSQL] Skip Locked๋ฅผ ์ด์šฉํ•œ queue consume

๊ด€๋ จ ํฌ์ŠคํŠธ
https://m.blog.naver.com/sssang97/222910699714

Lock์€ Postgresql์„ ๋น„๋กฏํ•œ RDB์˜ ํ•ต์‹ฌ์š”์†Œ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์›์ž์„ฑ๊ณผ ๋™์‹œ์„ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ•˜์ง€๋งŒ ์œ ์ฆˆ์ผ€์ด์Šค์— ๋”ฐ๋ผ์„œ๋Š” ์ด lock์ด ๋ณ‘๋ชฉ์ด ๋˜์–ด์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์ด๋ฅผํ…Œ๋ฉด "์ž‘์—… ํ" ๊ฐ™์€ ๋‹จ์ˆœ ์“ฐ๊ธฐ/์ฝ๊ธฐ๊ฐ€ ๋ฌด์‹ํ•˜๊ฒŒ ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ๋•Œ ๋ง์ด๋‹ค.

ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•œ ํ…Œ์ด๋ธ” ๊ตฌ์„ฑ์€ ์ด๋Ÿฐ์‹์ด๋‹ค.
๋‹จ์ˆœํ•œ key-value ํ˜•ํƒœ์˜ ํ๋‹ค.

create table queue
(
    id serial primary key,
    data jsonb
);

insert into queue(data)
select to_jsonb('{ "value": "' || generate_series(1, 10000)::TEXT || '" }');

์•„๋ž˜ ์ฟผ๋ฆฌ๋Š” ํ์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ๊ฑธ ์ˆœ์„œ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฐ„๋‹จํ•œ ์ฟผ๋ฆฌ๋‹ค. ๋™์‹œ์— ํ•œ๋†ˆ๋งŒ ํ•˜๋‚˜์”ฉ ๊ฐ€์ ธ์˜ค๋„๋ก for update๋กœ ๋ฝ์„ ๊ฑธ์—ˆ๋‹ค. ์•„๋งˆ ๊ฐ€์ ธ์˜จ ํ›„์—๋Š” ์ ์ ˆํžˆ ์‚ญ์ œ ์ž‘์—…์„ ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

select * from queue
order by id
limit 1
for update;

๊ทธ๋Ÿฐ๋ฐ ์ € ์ฟผ๋ฆฌ๊ฐ€ ์™„์ „ํžˆ ๋™์‹œ์— ๋ช‡๊ฐœ ๋ช‡์‹ญ๊ฐœ๊ฐ€ ์‹คํ–‰๋œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
for update๋กœ ๊ฑธ๋ฆฐ ๋ฝ ๋•Œ๋ฌธ์— ์•„๋งˆ ํ•œ๋†ˆ์”ฉ๋งŒ ์‹คํ–‰๋˜๊ฒŒ ๊ธฐ๋‹ค๋ฆด ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ ํ…Œ์ŠคํŠธ๊ฒธ ๋ณ‘๋ ฌ๋กœ ๋™์‹œ์— ํ์—์„œ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด์„œ ์ง€์šฐ๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•ด๋ณด์•˜๋‹ค.
์‹ค์ œ๋กœ ํ๋ฅผ ํ™œ์šฉํ•  ๋•Œ๋Š” ์ด๋Ÿฐ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ผ์ด ๊ฝค ์žฆ์„ ๊ฒƒ์ด๋‹ค.

์ด๋ ‡๊ฒŒ ์‹คํ–‰ํ•˜๋ฉด, ๋™์ž‘ ์ž์ฒด๋Š” ์ž˜ ๋˜๊ธด ํ•œ๋‹ค.

๋ฌธ์ œ๋Š” ์ € ์ฟผ๋ฆฌ ํ•˜๋‚˜ํ•˜๋‚˜๊ฐ€ ๋‹ค ๋ฝ์„ ๊ฑธ์–ด๋ฒ„๋ฆฐ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
select๊ฐ€ id=3์งœ๋ฆฌ๋ฅผ ์žก๊ณ  ์žˆ์œผ๋ฉด ๋‹ค๋ฅธ ์ฟผ๋ฆฌ๋“ค์€ ๋‹ค ์ € ํŠธ๋žœ์žญ์…˜์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
๊ทธ๋ž˜์„œ ๊ณ„์† ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒํ•ด์„œ ์„ฑ๋Šฅ ์ž์ฒด๋„ ๋А๋ ค์ง€๊ณ , ๊ณ„์† ๋ฝ์„ ์žก๊ณ ์žˆ์œผ๋‹ˆ ํŠธ๋žœ์žญ์…˜ ํƒ€์ž„์•„์›ƒ์ด ๊ฑธ๋ฆฌ๊ธฐ๋„ ํ•œ๋‹ค.
๋ช‡๊ฐœ ์‹คํŒจํ–ˆ๋Š”๋ฐ๋„ 61์ดˆ๊ฐ€ ๊ฑธ๋ ธ๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ์œ ์ฆˆ์ผ€์ด์Šค์˜ ๊ฒฝ์šฐ์—๋Š” ์ด๋ฏธ ๋ฝ์ด ๊ฑธ๋ฆฐ ๋†ˆ์„ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ๋„๋ก Skip Locked์„ ๊ฑธ์–ด์ฃผ๋ฉด ๋ฌธ์ œ๋ฅผ ์ข€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

select * from queue
order by id
limit 1
for update
skip locked;๏ปฟ

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•˜๋‚˜์”ฉ ์ฝ์–ด์˜ค๋˜, ๋ฝ์ด ๊ฑธ๋ฆฐ ํ•ญ๋ชฉ์€ ์•„์˜ˆ ๋ฌด์‹œํ•˜๊ณ  ๊ฐ€์ ธ์˜จ๋‹ค.

ํŠธ๋žœ์žญ์…˜ ํƒ€์ž„์•„์›ƒ๋„ ์‚ฌ๋ผ์กŒ๊ณ , ์‹คํ–‰์‹œ๊ฐ„๋„ ์กฐ๊ธˆ๋” ๋นจ๋ผ์กŒ๋‹ค.

์ด ๊ฒฝ์šฐ์—๋Š” 5๋งŒ๊ฐœ์งœ๋ฆฌ ์Šค๋ชฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ค„์„œ ํฐ ์ฐจ์ด๊ฐ€ ๋‚˜์ง€๋Š” ์•Š์•˜์ง€๋งŒ, ์–‘์ด ๋งŽ์•„์งˆ ์ˆ˜๋ก ๊ทธ ๊ฐ„๊ทน์€ ๋” ๋„“์–ด์งˆ ๊ฒƒ์ด๋‹ค.



์ฐธ์กฐ
https://www.pgcasts.com/episodes/the-skip-locked-feature-in-postgres-9-5
https://www.cybertec-postgresql.com/en/skip-locked-one-of-my-favorite-9-5-features/