[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/