๐ ๊ฐ์
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 ์ ์ฌ์ฉํ ๋ ๋ค์๊ณผ ๊ฐ์ ์ํฉ์ ์ฃผ์ํ์!
- ์กฐ๊ฑด์ ์ ์ธ๋ฑ์ค ์ปฌ๋ผ์ด ํ๋๋ ์กด์ฌํ์ง ์๋๋ค๋ฉด ์ธ๋ฑ์ค์ ๋ชจ๋ ๋ ์ฝ๋๊ฐ ์ ๊ธด๋ค. ์ธ๋ฑ์ค๊ฐ ์๋ ์ปฌ๋ผ์ผ๋ก ๋ฝ ์กฐํ๋ฅผ ํด์ผ ํ ๊ฒฝ์ฐ, ํด๋น ์ปฌ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ์ค์ ํ ๊ฒ์ ๊ณ ๋ คํด ๋ณด์.
- ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค์ด REPEATABLE_READ ๋ผ๋ฉด, ๊ฐญ ๋ฝ์ ์ํด ์๋ํ์ง ์์ ํฐ ๋ฒ์์ ์ ๊ธ์ด ๊ฑธ๋ฆด ์๋ ์๋ค. ์ด ๊ฒฝ์ฐ, ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค์ READ_COMMITED ๋ก ๋ฎ์ถ๋ ๋ฐฉ๋ฒ์ ๊ณ ๋ คํด ๋ณด์.