๋ฉํฐ ํธ๋์ญ์ ํ๊ฒฝ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ผ๊ด์ฑ๊ณผ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ ค๋ฉด ํธ๋์ญ์ ์ ์์ฐจ์ ์งํ์ ๋ณด์ฅํ ์ ์๋ ์ง๋ ฌํ ์ฅ์น๊ฐ ํ์ํ๋ค. DB๋ ์ฌ๋ฌ ๊ฒฉ๋ฆฌ ์์ค๊ณผ Lock ๋ฐฉ์์ด ์กด์ฌํ๋ค.
DB๊ฐ ์ค์ ํ๋ ๊ฒฉ๋ฆฌ ์์ค์ ์๋ 4๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ ์๋๋ค.
๊ฐ๊ฐ์ ๊ฒฉ๋ฆฌ ์์ค์์ ๋ฐ์ํ๋ ๋ฌธ์ ์ ๋ค์ด ์กด์ฌํ๋ ํ ๋ฒ ์ฐพ์๋ณด๋ ๊ฒ๋ ๋์์ด ๋ ๊ฒ์ด๋ค.
Mysql์ REPEATABLE READ๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ค. ํด๋น ๊ฒฉ๋ฆฌ ์์ค์์ ๋ฐ์ํ๋ PANTHOM READ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋๋ฐ InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ๋ฅ์คํธ ํค ๋ฝ (Next key lock)์ ์ด์ฉํ์ฌ ํด๊ฒฐํ์๋ค.
MySQL ํธ๋์ญ์ ๊ณผ ๋ฝ - InnoDB ๋ฝ, ์ด๋ ๊ฒ ๋์ํ๋ค!
๋ํ์ ์ผ๋ก ์๋ 2๊ฐ์ง์ Lock์ด ์กด์ฌํ๋ค.
ํน์ Row๋ฅผ ์ฝ์(Read) ๋ ์ฌ์ฉ๋๋ค. A ํธ๋์ญ์ ์์ ํน์ Row์ S-Lock์ ๊ฑธ์๋ค๋ฉด, B ํธ๋์ญ์ ์์๋ ์ฝ๊ธฐ๋ ๊ฐ๋ฅํ์ง๋ง ์ฐ๊ธฐ๋ ๋ถ๊ฐ๋ฅํ๋ค.
์ฆ, ๋ค๋ฅธ ํธ๋์ญ์ ์์ S-Lock์ ๊ฑธ ์ ์์ง๋ง X-Lock์ ๊ฑธ ์ ์๋ค.
ํน์ Row๋ฅผ ๋ณ๊ฒฝ(Write)ํ ๋ ์ฌ์ฉ๋๋ค. A ํธ๋์ญ์ ์์ ํน์ Row์ X-Lock์ ๊ฑธ์๋ค๋ฉด, B ํธ๋์ญ์ ์์๋ ํด๋น Row๋ฅผ ์ฝ๊ธฐ, ์ฐ๊ธฐ ๋ชจ๋ ๋ถ๊ฐ๋ฅํ๋ค. ํด๋น A ํธ๋์ญ์ ์ด ๊ฑด Lock์ด ์ข ๋ฃ๋๊ธธ ๊ธฐ๋ค๋ฆฐ๋ค.
์ฆ, ๋ค๋ฅธ ํธ๋์ญ์ ์์ S-Lock, X-Lock์ ๊ฑธ ์ ์๋ค.
X-Lock์ SELECT ... FOR UPDATE, UPDATE, DELETE ๋ฑ์ ๋ณ๊ฒฝ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ฉด ๊ฐ๊ฐ์ Row๋ง๋ค ์ ๊ธ์ด ๊ฑธ๋ฆฌ๋ Row-Level-Lock์ด๋ค.
ํ ์ด๋ธ ์์ ํน์ Row์ ๋ํด์ ๋์ค์ ์ด๋ค Row-Level Lock์ ๊ฑธ ๊ฒ์ด๋ผ๋ ์๋๋ฅผ ์๋ ค์ฃผ๊ธฐ ์ํด ๋ฏธ๋ฆฌ Table-Level์ ๊ฑธ์ด๋๋ Lock์ด๋ค.
Intention Shared Lock (IS), Intention Exclusive Lock (IX) ์กด์ฌํ๋ค.
SELECT ... LOCK IN SHARE MODE
์ด ์คํ๋๋ฉด,SELECT ... FOR UPDATE, INSERT, DELETE, UPDATE
์ด ์คํ๋๋ฉด,Q. Table-level์์ ํ๋ฒ, Row-Level์์ ํ๋ฒ, 2๋จ๊ณ(2-phase)๋ก Lock์ ์ ์ฉํ๋ ์ด์ ๋?
A. ํธ๋์ญ์ A์์ ์ด๋ฏธ ํ ์ด๋ธ์ ๋ํด ๋ฝ์ด ๊ฑธ๋ ค์๋๋ฐ, ํธ๋์ญ์ B์์ ํด๋น ํ ์ด๋ธ์ ํน์ Row์ Lock์ ๊ฑฐ๋๊ฒ์ ์์ฒ์ ์ผ๋ก ๋ฐฉ์ง ํ ์ ์๋ค. ๋ฐ๋์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค.
๐ก UPDATE ํ ๋!
๋ณดํต์ย UPDATE๋๋ ๋์ row์ย Lock์ด ๊ฑธ๋ฆฌ์ง๋ง, WHERE ์ ์ ์ธ๋ฑ์ค๋ฅผ ์ ์ ํ ํ์ฐ์ง ์๊ฑฐ๋ ์ธ๋ฑ์ค๊ฐ ์๋ ๊ฒฝ์ฐ๋ย ํ
์ด๋ธ ์ ์ฒด์ Lock์ด ๊ฑธ๋ฆฐ๋ค.
Lock์ ์ข ๋ฅ (Shared Lock, Exclusive Lock, Record Lock, Gap Lock, Next-key Lock)
๋๋ SELECT๋ฅผ ํ๋ฉด ํด๋น Row์ S-Lock์ด ๊ฑธ๋ฆฐ๋ค๊ณ ์๊ฐํ ์ ์ด ์๋ค. S-Lock์ ๊ฐ๋ ์ ์ผ๋ก ์ดํดํ ํ ์ฝ๊ธฐ๋ SELECT ์ ์ ์๋ฏธํ๋ค๊ณ ์คํดํ๋ค.๐ฅ ์ดํ DeadLock ๋ฐ์ ์์ธ์ ํธ๋ํน ํ๋ฉด์ ์ดํดํ๋ค๊ณ ์๊ฐํ๋ S-Lock์ ๊ต์ฅํ ํผ๋์ด ์์ ์ง๊ธ ๋ค์ ํ์ตํ๊ณ ์ ํ๋ค.
์ผ๋ฐ์ ์ธ SELECT ์ฟผ๋ฆฌ๋ ์ ๊ธ์ ์ฌ์ฉํ์ง ์๊ณ DB๋ฅผ ์ฝ์ด ๋ค์ธ๋ค. SELECT๋ ํน์ Row๋ฅผ ์ฝ์ ํ์์ผ๋ฟ์ด์ง ์ ๊ธ์ ์๋ฏธํ๋ ๊ฒ์ ์๋๋ค ๋ผ๋ ๋ง์ด ๊น์ด ์๋ฟ์๋ค.
์ค์ ํ ์คํธ๋ฅผ ์งํํ์ ๋ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ๋ณ๊ฒฝ(Write)๊ฐ ๊ฐ๋ฅํ ๊ฒ์ ์ง์ ํ์ธํ๋ค.
ํน์ Row๋ฅผ ์กฐํ ์์ X-Lock์ ๊ฑธ ์ ์๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ค. ๋ช ์นญ์ ๋ณด๋๋ผ๋ UPDATE ์ ์ ์ํด Row ์กฐํ๋ฅผ ํ์๊ณ ํธ๋์ญ์ ์ด ์ข ๋ฃ๋ ๋๊น์ง ๋ณ๊ฒฝ๋๊ธธ ์์น ์๋๋ค! ๋ผ๋ ๊ฒ์ ์ ์ ์๋ค.
SQL ๋ฌธ๋ฒ์ผ๋ก๋ SELECT ์ ๋ค์ FOR UPDATE๋ฅผ ์ถ๊ฐํ๋ค.
SELECT * FROM USERS FOR UPDATE
JPA์์๋ Repository์ @Lock ์ด๋ ธํ ์ด์ ์ผ๋ก ์ ๊ธ์ ์ค์ ํ๋ค.
public interface UserRepository extends JpaRepository<User, Long> {
@Lock(LockModeType.PESSIMISTIC_READ)
User findById(Long id);
}
์ฐธ๊ณ ๋ก @Lock ์ด๋ ธํ ์ด์ ์๋ ์๋์ ๊ฐ์ ์ ๊ธ์ด ์กด์ฌํ๋ค.
@Lock(LockModeType.PESSIMISTIC_READ)
ํด๋น ๋ฆฌ์์ค์ ๊ณต์ ์ ๊ธ์ ๊ฑด๋ค. ๋ค๋ฅธ ํธ๋์ญ์
์์ ์ฝ๊ธฐ๋ ๊ฐ๋ฅํ์ง๋ง ์ฐ๊ธฐ๋ ๋ถ๊ฐ๋ฅํ๋ค.
@Lock(LockModeType.PESSIMISTIC_WRITE)
ํด๋น ๋ฆฌ์์ค์ ๋ฐฐํ์ ์ ๊ธ์ ๊ฑด๋ค. ๋ค๋ฅธ ํธ๋์ญ์
์์๋ ์ฝ๊ธฐ์ ์ฐ๊ธฐ ๋ชจ๋ ๋ถ๊ฐ๋ฅํ๋ค.
@Lock(LockModeType.PESSIMISTIC_FORCE_INCREMENT)
PESSIMISTIC_WRITE์ ์ ์ฌํ๊ฒ ์๋ํ์ง๋ง ์ถ๊ฐ์ ์ผ๋ก ๋๊ด์ ์ ๊ธ์ฒ๋ผ ๋ฒ์ ๋์ ํ๋ค. ๋ฐ๋ผ์ ๋ฒ์ ์ ๋ํ ์นผ๋ผ์ด ํ์ํ๋ค.
Select ์ฟผ๋ฆฌ๋ S๋ฝ์ด ์๋๋ค. (X๋ฝ๊ณผ S๋ฝ์ ์ฐจ์ด)
์ธ๋ํค ์นผ๋ผ์ ๋ณ๊ฒฝ(INSERT, UPDATE) ์ ๋ถ๋ชจ ํ ์ด๋ธ์ด๋ ์์ ํ ์ด๋ธ์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ ์ง ํ์ธ ์ ์ฐจ๊ฐ ํ์ํ๋ค. ์ ๊ธ์ด ์ฐ๊ด ๊ด๊ณ๋ฅผ ๋งบ๊ณ ์๋ ์ฌ๋ฌ ํ ์ด๋ธ๋ก ์ ๊ธ์ด ์ ํ๋๋ค. ํด๋น ๋ณ๊ฒฝ ์์ ์ ์ํด ์ธ๋ํค ์ปฌ๋ผ์ S-Lock์ด ๊ฑธ๋ฆฌ๊ฒ ๋๊ณ ๊ทธ๋ก ์ธํด ๋ฐ๋๋ฝ(DeadLock) ๋ฐ์ ์์ธ์ด ๋ ์ ์์์ผ๋ก ์ฃผ์ํด์ผ ํ๋ค.
๋ฉํฐ ํธ๋์ญ์ ๊ฐ ๊ต์ฐฉ ์ํ๋ฅผ ์๋ฏธํ๋ค. ์ ๊ธ ๋๋ฌธ์ ์๋ก์ ์ ๊ธ์ด ํ๋ฆฌ๊ธฐ๋ฅผ ๋ฌดํํ ๋๊ธฐํ๋ ์ํฉ์ด๋ค. ๋ณดํต์ ํธ๋์ญ์ ์ ์ฟผ๋ฆฌ ์์๋ฅผ ์กฐ์จํ์ฌ ์ฒ๋ฆฌํ ์ ์๊ณ ๋๊ด์ ์ ๊ธ(Optimistic Lock)์ผ๋ก ์ด๋ ์ ๋์ ๋กค๋ฐฑ์ ํ์ฉํ๋ฉฐ ์ฒ๋ฆฌํ ์ ์๋ค.
๋ฐ๋๋ฝ์ ๋ฐ์ ์์ธ์ ํ๋ฒ์ ์ถ์ ํ๊ธฐ๋ ์ฝ์ง ์๋ค. ์ํ๋ฅผ ๋ณด์ฌ์ฃผ๋ SQL๋ฌธ์ ์คํํ๋ฉด latest detection deadlock
๋ถ๋ถ์ด ์กด์ฌํ์ฌ ์ต๊ทผ์ ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ฟผ๋ฆฌ๋ฅผ ํ์ธ ๊ฐ๋ฅํ๋ค.
SHOW ENGINE INNODB STATUS
APM(Application Performance Management)
์ด๋ฒ ๊ฒฝ์ฐ์๋ APM์ ์ฌ์ฉํ์ฌ ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ํธ๋์ญ์ ๊ณผ ๊ฐ์ ์๊ธฐ์ ์คํ๋๊ณ ์ถฉ๋์ด ๋ฐ์ํ ๋งํ ์ฟผ๋ฆฌ๋ฅผ ์์ํด๋ณผ ์ ์์๋ค.
(Exception์ด ๋ฐ์ํ ๋ ๋ฐ๋๋ฝ์ด ๋ฐ์ํ 2๊ฐ์ ์ฟผ๋ฆฌ ๋ชจ๋ ๋ก๊ทธ๋ฅผ ์ฐ์ด์ฃผ๋ฉด ์์ธ ๋ถ์์ด ์ฌ์ธํ ๋ฐโฆ๐ฅ)
์ฟผ๋ฆฌ ์์๋ฅผ ํ์ธํด๋ณด๋ ์ธ๋ํค์ ์ํ ์ ๊ธ ์ ํ๊ฐ ์ด๋ฒ ๋ฐ๋๋ฝ์ ๋ฐ์ ์์ธ์ด์๋ค.
์ฟผ๋ฆฌ ์คํ ์์๋ฅผ ์์ฐจ์ ์ผ๋ก ํ์ธํด๋ณด์.
ํธ๋์ญ์
A๋ ํฌ์ง์
(Position) ํ
์ด๋ธ์ ํน์ Row ๋ณ๊ฒฝ์ ์ํด X-Lock์ ๊ฑด๋ค.
- PK์ ๋ํ ์ธ๋ฑ์ค๋ฅผ ํ๊ธฐ ๋๋ฌธ์ Table-Level Lock์ ๊ฑธ๋ฆฌ์ง ์๋๋ค.
ํธ๋์ญ์
B๋ Row์ INSERT ์ ์ ์คํํ๋ ค ํ๋ค. ๋ฉ์์ง(Message) ํ
์ด๋ธ์ ์ง์์(Applicant), ํฌ์ง์
(Position) ํ
์ด๋ธ์ ์ธ๋ํค๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
- 16535 PK์ ์ง์์๋ฅผ ์กฐํํ์ฌ S-Lock์ด ์ ํ๋๋ค.
- 1446 PK์ ํฌ์ง์
์ ์กฐํํ์ฌ S-Lock์ด ์ ํ๋๋๋ฐ ํธ๋์ญ์
A์์ ์ด๋ฏธ X-Lock์ด ๊ฑธ๋ ธ์ผ๋ฏ๋ก ๋๊ธฐ ์ํ๊ฐ ๋๋ค.
ํธ๋์ญ์ A์์ 16535 PK์ ์ง์์(Applicant)๋ฅผ ๋ณ๊ฒฝํ๋ ค ํ๋ค. ํธ๋์ญ์ B์์ X-Lock์ด ๊ฑธ๋ ธ์ผ๋ฏ๋ก ๋๊ธฐ ์ํ๊ฐ ๋๋ค.
ํธ๋์ญ์ A, B๊ฐ ์๋ก์ ์ ๊ธ์ด ํ๋ฆฌ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๊ต์ฐฉ ์ํ์ ๋น ์ง๋ค.
๊ฐ๋จํ๊ฒ ํธ๋์ญ์ A์ ์ฟผ๋ฆฌ ์คํ ์์๋ฅผ ๋ค๋ฐ๊ฟ์ฃผ๋ฉฐ ๊ต์ฐฉ ์ํ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
์ง์์(Applicant)์ UPDATE ์ ์ ๋จผ์ ์คํํ๊ณ ํฌ์ง์ (Position)์ UPDATE ์ ์ ์ฒ๋ฆฌํ๋ค. 16535 PK์ ์ง์์ Row์ ๋ํด ๋จผ์ X-Lock์ ํ๋ํ๊ธฐ ๋๋ฌธ์ ํธ๋์ญ์ B์ INSERT๋ ์ธ๋ํค์ธ ์ง์์๋ฅผ ์กฐํํ๋ ๊ณผ์ ์์ ๋๊ธฐ ์ํ๊ฐ ๋๋ค.