๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

database

[MySQL] InnoDB ์˜ ์ž ๊ธˆ ๋ฐฉ์‹: ๋ ˆ์ฝ”๋“œ๋ฝ, ๊ฐญ๋ฝ, ๋„ฅ์ŠคํŠธํ‚ค๋ฝ

๐Ÿš€  ๊ฐœ์š”

RealMySQL ์ฑ…์„ ์ฝ๋‹ค๊ฐ€ InnoDB ์Šคํ† ๋ฆฌ ์—”์ง„์ด ์ œ๊ณตํ•˜๋Š” ๋ฝ์ธ ๋ ˆ์ฝ”๋“œ๋ฝ, ๊ฐญ๋ฝ, ๋„ฅ์ŠคํŠธํ‚ค๋ฝ์— ๋Œ€ํ•ด ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์ด ์ž ๊ธˆ๋“ค์ด ๋ฌด์—‡์ด๊ณ  ์–ด๋–ค ์ž ๊ธˆ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž.

ํšŒ์› ํ…Œ์ด๋ธ”

๋ฐฑ๋‚  ๊ฐœ๋…๋งŒ ์ฝ์–ด๋ดค์ž ์ž˜ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ฐ„๋‹จํ•œ ํšŒ์› ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜์—ฌ ์‹ค์ œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค๋ณด๋ฉฐ ๋ฝ์„ ์ดํ•ดํ•ด๋ณด์ž. ํšŒ์› ํ…Œ์ด๋ธ”์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํšŒ์› ์•„์ด๋””(member_id), ํšŒ์› ์ด๋ฆ„(name), ํšŒ์› ๋‹‰๋„ค์ž„(nickname), ํšŒ์› ๋‚˜์ด(age)๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

10๊ฐœ์˜ ํšŒ์› ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค. ์ด์ œ ์ด ๋ฐ์ดํ„ฐ์— ๋ฝ์„ ๊ฑธ์–ด๋ณด๋ฉฐ ์‹คํ—˜ํ•ด๋ณด์ž.

๐Ÿ“– InnoDB ์˜ ๋ ˆ์ฝ”๋“œ๋ฝ

InnoDB ๋Š” ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์ธ๋ฑ์Šค์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ž ๊ทผ๋‹ค. InnoDB ์˜ ๋ ˆ์ฝ”๋“œ๋ฝ์˜ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ธ๋ฑ์Šค๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰๋˜๋Š” ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๋ฅผ ์ž ๊ทผ๋‹ค.
  • ์กฐ๊ฑด์ ˆ์— ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ์ด ์—†๋‹ค๋ฉด ํ…Œ์ด๋ธ”์„ ํ’€์Šค์บ”ํ•˜๋ฉด์„œ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๋ฅผ ์ž ๊ทผ๋‹ค.
  • ํ…Œ์ด๋ธ”์— ์ธ๋ฑ์Šค๊ฐ€ ํ•˜๋‚˜๋„ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, ๋‚ด๋ถ€์ ์œผ๋กœ ์ž๋™ ์ƒ์„ฑ๋œ ํด๋Ÿฌ์Šคํ„ฐ ์ธ๋ฑ์Šค๋ฅผ ์ด์šฉํ•ด ์ž ๊ธˆ์„ ์„ค์ •ํ•œ๋‹ค.
  • ์ธ๋ฑ์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด ๋” ์ข์€ ๋ฒ”์œ„์˜ ์ธ๋ฑ์Šค๋ฅผ ์ž ๊ทผ๋‹ค.

ํšŒ์› ํ…Œ์ด๋ธ”์—์„œ ์„ค์ •ํ•œ ์ธ๋ฑ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๐Ÿงช ์‹คํ—˜ 1. PK ์กฐ๊ฑด์˜ ์ž ๊ธˆ

select * from member where member_id=1 for update ;

๐Ÿ”‘ Lock

  • member_id ๊ฐ€ 1 ์ธ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊น€

๐Ÿงช ์‹คํ—˜ 2. UNIQUE ์กฐ๊ฑด์˜ ์ž ๊ธˆ

select * from member where nickname='nickname1' for update ;

๐Ÿ”‘ Lock

  • member_id ๊ฐ€ 1์ธ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊น€
  • nickname ๊ฐ€ 'nickname1' ์ธ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊น€

๐Ÿงช ์‹คํ—˜ 3. NON-UNIQUE ์ธ๋ฑ์Šค ์กฐ๊ฑด์˜ ์ž ๊ธˆ

select * from member where age=20 for update ;

๐Ÿ”‘ Lock

  • member_id ๊ฐ€ 1, 4, 5 ์ธ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊น€
  • age ๊ฐ€ 20 ์ธ ๋ ˆ์ฝ”๋“œ๋“ค์ด ์ž ๊น€
  • age 20 ๋ฐ”๋กœ ๋‹ค์Œ์˜ ์ธ๋ฑ์Šค์ธ 23 ์— ๊ฐญ๋ฝ์ด ๊ฑธ๋ฆผ(๊ฐญ๋ฝ์€ ๋’ค์—์„œ ์„ค๋ช…)

๐Ÿงช ์‹คํ—˜ 4. ์ธ๋ฑ์Šค๊ฐ€ ์•„๋‹Œ ์กฐ๊ฑด์˜ ์ž ๊ธˆ

select * from member where name='a' for update ;

๐Ÿ”‘ Lock

  • ์ธ๋ฑ์Šค์˜ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊น€

๐Ÿ“– ๊ฐญ(GAP)๋ฝ์ด๋ž€?

๋ ˆ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ์•„๋‹Œ ๋ ˆ์ฝ”๋“œ์™€ ๋ฐ”๋กœ ์•ž์— ์ธ์ ‘ํ•œ ๋ ˆ์ฝ”๋“œ ์‚ฌ์ด์˜ ๊ฐ„๊ฒฉ๋งŒ์„ ์ž ๊ทธ๋Š” ๋ฝ์ด๋‹ค. REPEATABLE_READ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์—์„œ ๋™์ž‘ํ•˜๋ฉฐ, ๋ ˆ์ฝ”๋“œ์™€ ๋ ˆ์ฝ”๋“œ ์‚ฌ์ด์˜ ๊ฐ„๊ฒฉ์— ์ƒˆ๋กœ์šด ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ(INSERT)๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค. MySQL ์˜ REPEATABLE_READ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์—์„œ ๋ฝ ์กฐํšŒ์—์„œ Phantom Read ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋„ ๊ฐญ๋ฝ์„ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋„ฅ์ŠคํŠธํ‚ค๋ฝ์€ ๋ ˆ์ฝ”๋“œ๋ฝ๊ณผ ๊ฐญ๋ฝ์„ ํ•ฉ์ณ๋†“์€ ๊ฒƒ์ด๋‹ค.

LOCK_MODE

X, REC_NOT_GAP X, GAP X
๋ ˆ์ฝ”๋“œ๋ฝ ๊ฐญ๋ฝ ๋„ฅ์ŠคํŠธํ‚ค๋ฝ(๋ ˆ์ฝ”๋“œ๋ฝ + ๊ฐญ๋ฝ)

๐Ÿงช ์‹คํ—˜ 1. PK ์กฐ๊ฑด์˜ ๋‹จ์ผ ์ž ๊ธˆ

select * from member where member_id=1 for update ;

๐Ÿ”‘ Lock

UNIQUE ์ธ๋ฑ์Šค(PK, UNIQUE KEY) ์กฐ๊ฑด์˜ ๋‹จ์ผ ์ž ๊ธˆ์€ ๊ฐญ๋ฝ์ด ๊ฑธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ์œ ์ผํ•œ ๊ฐ’์— ๋Œ€ํ•ด์„œ๋Š” ๊ฐ„๊ฒฉ ์ž ๊ธˆ์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๐Ÿงช ์‹คํ—˜ 2. PK ์กฐ๊ฑด์˜ ๋ฒ”์œ„ ์ž ๊ธˆ

select * from member where member_id between 7 and 15 for update ;

๐Ÿ”‘ Lock

  • member_id ๊ฐ€ 7, 8, 9, 10 ์ธ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊น€
  • member_id ๊ฐ€ 7~8, 8~9, 9~10 ์ธ ๊ฐ„๊ฒฉ์ด ์ž ๊น€
  • ์ธ๋ฑ์Šค์— ์กด์žฌํ•˜๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’(10~) ์ดํ›„์˜ ๋ชจ๋“  ๊ฐ„๊ฒฉ์ด ์ž ๊น€(supremum pseudo-record)

member_id ๊ฐ€ 7~15 ์‚ฌ์ด๋Š” ๋ฌผ๋ก  15 ์ด์ƒ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฝ์ž…๋  ์ˆ˜ ์—†๋‹ค. ์ƒํ•œ ๊ฐ’์ธ 15 ๊ฐ€ ํ˜„์žฌ ์ธ๋ฑ์Šค์— ์กด์žฌํ•˜๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’์ธ 10 ๋ณด๋‹ค ํฌ๊ธฐ ๋•Œ๋ฌธ์— 10 ์ดํ›„์˜ ๊ฐ„๊ฒฉ์ด ์ž ๊ธด ๊ฒƒ์ด๋‹ค. 

๐Ÿงช ์‹คํ—˜ 3.NON-UNIQUE ์ธ๋ฑ์Šค ์กฐ๊ฑด์˜ ๋‹จ์ผ ์ž ๊ธˆ

select * from member where age=20 for update ;

๐Ÿ”‘ Lock

  • age ๊ฐ€ ์ธ๋ฑ์Šค๊ฐ€ 20 ์ธ ๋ ˆ์ฝ”๋“œ๋“ค๊ณผ ๊ฐ„๊ฒฉ์ด ์ž ๊น€
  • age ๊ฐ€ 20~23 ์ธ ๊ฐ„๊ฒฉ์ด ์ž ๊น€

age ๊ฐ€ 20~23 ์ธ ๊ฐ„๊ฒฉ์— ๊ฐญ๋ฝ์ด ๊ฑธ๋ ค, ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ age ๊ฐ€ 20 ์ธ ํšŒ์›์„ ๋ฝ ์กฐํšŒ๋ฅผ ํ•  ๋•Œ ํ•ญ์ƒ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์กฐํšŒ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค.

๐Ÿงช ์‹คํ—˜4. NON-UNIQUE ์ธ๋ฑ์Šค ์กฐ๊ฑด์˜ ๋ฒ”์œ„ ์ž ๊ธˆ

select * from member where age between 23 and 27 for update ;

๐Ÿ”‘ Lock

  • age ๊ฐ€ 23, 27, 28 ์ธ ๋ ˆ์ฝ”๋“œ๋“ค๊ณผ ๊ฐ„๊ฒฉ์ด ์ž ๊น€

age ๊ฐ€ 28 ์ธ ๋ฐ์ดํ„ฐ์—๋Š” ๊ฐญ๋ฝ๋งŒ ๊ฑธ๋ ค๋„ Phantom Read ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์€๋ฐ ๋„ฅ์ŠคํŠธํ‚ค๋ฝ์ด ๊ฑธ๋ฆฌ๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ผ๊นŒ? ์ด ๋ถ€๋ถ„์€ ์•Œ๊ฒŒ๋˜๋ฉด ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด์•ผ๊ฒ ๋‹ค.

๐Ÿ”š ๊ฒฐ๋ก 

์ด๋ฒˆ์— InnoDB ์˜ ๋ฝ์„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๋„ํ•˜์ง€ ์•Š์€ ๋ฝ์ด ๊ฑธ๋ฆฌ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์˜๋„ํ•˜์ง€ ์•Š์€ ๋ฝ์œผ๋กœ ์ธํ•ด ๋™์‹œ์„ฑ์ด ๋–จ์–ด์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ MySQL ์„ ์‚ฌ์šฉํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์„ ์ฃผ์˜ํ•˜์ž!

  1. ์กฐ๊ฑด์ ˆ์— ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ์ด ํ•˜๋‚˜๋„ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ธ๋ฑ์Šค์˜ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ž ๊ธด๋‹ค. ์ธ๋ฑ์Šค๊ฐ€ ์—†๋Š” ์ปฌ๋Ÿผ์œผ๋กœ ๋ฝ ์กฐํšŒ๋ฅผ ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, ํ•ด๋‹น ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ๊ฒƒ์„ ๊ณ ๋ คํ•ด ๋ณด์ž.
  2. ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์ด REPEATABLE_READ ๋ผ๋ฉด, ๊ฐญ ๋ฝ์— ์˜ํ•ด ์˜๋„ํ•˜์ง€ ์•Š์€ ํฐ ๋ฒ”์œ„์— ์ž ๊ธˆ์ด ๊ฑธ๋ฆด ์ˆ˜๋„ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์„ READ_COMMITED ๋กœ ๋‚ฎ์ถ”๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด ๋ณด์ž.