DevLog ๐ถ
[Real MySQL 8.0] InnoDB์ ์ธ๋ฑ์ค์ ๋ฝ, ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค ๋ณธ๋ฌธ
[Real MySQL 8.0] InnoDB์ ์ธ๋ฑ์ค์ ๋ฝ, ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค
dolmeng2 2023. 6. 19. 00:51๐ฑ ๋ค์ด๊ฐ๊ธฐ ์
์ด๋ฒ ํฌ์คํ
์์๋ InnoDB์ ์ธ๋ฑ์ค์ ๋ฝ์ ์๊ด๊ด๊ณ์ ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค์ ๋ํด์ ์์๋ณด์.
๐ฑ ์ธ๋ฑ์ค์ ๋ฝ
์ง๋ ํฌ์คํ ์์ ๋ ์ฝ๋ ๋ฝ์ ๋ํด ์ ๋ฆฌํ ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉํธ๋ฅผ ๋จ๊ฒผ๋ค.
innoDB์ ๊ฒฝ์ฐ ๋ ์ฝ๋ ์์ฒด๋ฅผ ์ ๊ทธ๋ ๊ฒ๋ณด๋ค๋, ์ธ๋ฑ์ค์ ๋ ์ฝ๋๋ฅผ ์ ๊ทผ๋ค.
์ธ๋ฑ์ค๋ฅผ ์ ๊ทธ๊ธฐ ๋๋ฌธ์ ๋ ์ฝ๋ ๊ฒ์ ์ ๋ฐ๊ฒฌ๋ ๋ชจ๋ ๋ ์ฝ๋์ ๋ฝ์ ๊ฑธ๊ฒ ๋๋ค.
์๋ฅผ ๋ค์ด, crew ํ
์ด๋ธ์ age = 23์ธ ์ฌ๋์ด 100๋ช
์ด๋ผ๊ณ ์๊ฐํด๋ณด์.
์ด๋, age์๋ ์ธ๋ฑ์ค๊ฐ, name์๋ ์ธ๋ฑ์ค๊ฐ ๊ฑธ๋ ค์์ง ์์ ์ํ๋ค.
SELECT COUNT(*) FROM crew WHERE age = 23;
# result: 100
ํ์ง๋ง, age = 23์ด๋ฉด์ name = 'journey'์ธ ๊ฒฐ๊ณผ๋ 1๊ฐ๋ง ๋์จ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
SELECT COUNT(*) FROM crew WHERE age = 23 and name = 'journey';
# result: 1
์ด๋, age = 23์ด๊ณ name = 'journey'์ธ ๋ ์ฝ๋์ ๋ํด์ last_modified_at ๋ ์ฝ๋๋ฅผ NOW()๋ก ์
๋ฐ์ดํธํ๋ค๊ณ ์๊ฐํด๋ณด์.
UPDATE crew SET last_modified_at = NOW() WHERE age = 23 and name = 'journey';
์์ ์ฟผ๋ฆฌ๋ฌธ์ ์คํํ๊ธฐ ์ํด์ ๋ช ๊ฐ์ ๋ ์ฝ๋์ ๋ฝ์ ๊ฑธ๊ฒ ๋ ๊น?
๋ฐ๋ก, age = 23์ ๊ฒฐ๊ณผ๋ก ๋์จ 100๊ฐ์ ๋ ์ฝ๋์ ๋ํด์ ๋ชจ๋ ๋ฝ์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ค.
์ธ๋ฑ์ค๊ฐ ๋ง์ฝ ํ๋๋ ์๋ค๋ฉด ํ
์ด๋ธ์ ๋ํด ์ ์ฒด ์ค์บ (full-scan)์ ํ๋ฉด์ update๋ฅผ ์งํํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ ์ฝ๋์ ๋ํด์ ๋ฝ์ ๊ฑธ๊ฒ ๋ ๊ฒ์ด๊ณ , ์ฑ๋ฅ์ ์น๋ช
์ ์ธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค๋ฅผ ์ ๊ฑฐ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ๋ค!
MySQL 8.0๋ถํฐ๋ ๋ฝ์ ๋ํ ์ ๋ณด๋ฅผ performance_schema DB๋ฅผ ํตํด์ ํ์ธํ ์ ์๋ค.
SELECT
t1.trx_id waiting_trx_id,
t1.trx_mysql_thread_id waiting_thread,
t1.trx_query waiting_query,
t2.trx_id blocking_trx_id,
t2.trx_mysql_thread_id blocking_thread,
t2.trx_query blocking_query
FROM performance_schema.data_lock_waits w
INNER JOIN information_schema.INNODB_TRX t1 ON t1.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID
INNER JOIN information_schema.INNODB_TRX t2 ON t2.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID
waiting_trx_id์ ๊ฒฝ์ฐ ๋๊ธฐํ๊ณ ์๋ ํธ๋์ญ์
์ ์์ด๋๋ฅผ, waiting_thread๋ ๋๊ธฐํ๊ณ ์๋ ์ค๋ ๋์ ๋ฒํธ๋ฅผ, waiting_query๋ ๋๊ธฐํ๊ณ ์๋ ์ฟผ๋ฆฌ ์ ๋ณด๋ฅผ, blocking_trx_id๋ ๋ธ๋ฝํน ์ํ์ ์๋ ํธ๋์ญ์
์ ์์ด๋๋ฅผ, blocking_thread๋ ๋ธ๋ฝํน ์ํ์ ์๋ ์ค๋ ๋๋ฅผ, blocking_query๋ ๋ธ๋ฝํน ์ํ์ ์๋ ์ฟผ๋ฆฌ ์ ๋ณด๋ฅผ ์๋ฏธํ๋ค.
์ฌ๊ธฐ์ ๋๊ธฐ ์ํ๋ ํธ๋์ญ์
์ด ๋ค๋ฅธ ํธ๋์ญ์
์ ์์
์ด ์๋ฃ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ํ๋ฅผ, ๋ธ๋ฝํน ์ํ๋ ๋ค๋ฅธ ํธ๋์ญ์
์ด ์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ๋ฐ์ดํฐ๋ ๋ฝ์ ์์ฒญํ ์ํ๋ฅผ ์๋ฏธํ๋ค.
= ์ฆ, waiting_trx_id๊ฐ blocking_trx_id๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ ์ํ๋ฅผ ํ๋์ ํ์ธํ ์ ์๊ฒ ๋๋ค.
๋ฝ์ ํ๊ธฐ ์ํด์๋ blocking_trx_id๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฝ์ ํด์ ํ๊ณ , ๊ทธ ๋ค๋ก waiting_trx_id์ ์์
์ด ์ด๋ฃจ์ด์ ธ์ผ ํ๋ค.
๋ง์ฝ ๋ ์์ธํ ์ ๋ณด๋ฅผ ํ์ธํ๊ณ ์ถ๋ค๋ฉด data_locks์ ํ
์ด๋ธ์ ๋ชจ๋ ํ์ธํด๋ณด์.
SELECT * FROM performance_schema.data_locks;
์ฌ๊ธฐ์ engine_transaction_id์ thread_id, ๊ทธ๋ฆฌ๊ณ lock_type๊ณผ lock_mode์ ํ์ธํด๋ณด๋ฉด ์ด๋ค ํธ๋์ญ์
์ด ์ด๋ค ์ค๋ ๋๊ฐ ์ฌ์ฉํ๊ณ ์๊ณ , ์ด๋ค ๋ฝ์ ๊ฐ์ง๊ณ ์๋์ง๊น์ง ํ์ธ์ด ๊ฐ๋ฅํ๋ค. ๋ง์ฝ ๊ฒฐ๊ณผ์์ REC_NOT_GAP ์ด๋ผ๋ lock_mode๊ฐ ์๋ค๋ฉด ์ด๋ ๋ ์ฝ๋ ๋ฝ์์ ๊ฐญ์ด ํฌํจ๋์ง ์์ ์์ํ ๋ฝ์ ๊ฐ์ง๊ณ ์์์ ์๋ฏธํ๋ค. (lock_mode์ ๊ฒฐ๊ณผ๋ก๋ S[,GAP], X[,GAP], IS[,GAP], IX[,GAP], AUTO_INC ๋ฐ UNKNOWN๊ฐ ๋์ฌ ์ ์๋ค.)
๋ง์ฝ, ํน์ ์ค๋ ๋๊ฐ ๋ฝ์ ๋๋ฌด ์ค๋ ๋ณด์ ํ๊ณ ์๋ค๋ฉด ์๋์ ๊ฐ์ด KILL์ ํด์ฃผ์.
KILL thread_id
๐ฑ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค
ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค์ ์ฌ๋ฌ ํธ๋์ญ์
์ด ๋์์ ์ฒ๋ฆฌ๋ ๋ ํน์ ํธ๋์ญ์
์ด ๋ค๋ฅธ ํธ๋์ญ์
์์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์กฐํํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณผ ์ ์๋๋ก ํ ์ง ๋ง์ง ๊ฒฐ์ ํ๋ ๊ฒ์ด๋ค. ํฌ๊ฒ 4๊ฐ์ง์ ๊ฒฉ๋ฆฌ ์์ค์ด ์กด์ฌํ๋ฉฐ, READ UNCOMMITTED / READ COMMITTED / REPEATABLE READ / SERIALIZABLE๋ก ๋๋๋ค. Read Uncommitted์ Serializable์ ๊ฒฝ์ฐ ๋ณดํต ์ ์ฌ์ฉ๋์ง ์๋๋ค.
DIRTY-READ | NON-REPEATABLE READ | PHANTOM READ | |
READ UNCOMMITTED | O | O | O |
READ COMMITTED | X | O | O |
REPEATABLE READ | X | X | O (innoDB์์๋ ๋ฐ์ X) |
SERIALIZABLE | X | X | X |
์ค๋ผํด์์๋ Read Committed๋ฅผ ์ฌ์ฉํ๋ฉฐ, MySQL์์๋ Repeatable Read๋ฅผ ์ฃผ๋ก ์ฌ์ฉํ๋ค.
๐ฌ READ UNCOMMITTED
๊ธฐ๋ณธ์ ์ผ๋ก ์ปค๋ฐ์ด๋ ๋กค๋ฐฑ ์ฌ๋ถ์ ์๊ด์์ด ๋ค๋ฅธ ํธ๋์ญ์
์์ ํ์ธํ ์ ์๋ ๊ฒฉ๋ฆฌ ์์ค์ด๋ค.
์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด, ์์ง 'journey'๋ผ๋ ๋ ์ฝ๋๊ฐ ์ปค๋ฐ๋์ง ์์๋๋ฐ๋ ์ฌ์ฉ์ B๊ฐ ํด๋น ๋ด์ฉ์ read ํ ์ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์์
์ด ์๋ฃ๋์ง ์์๋๋ฐ๋ ๋ค๋ฅธ ํธ๋์ญ์
์์ ๋ณผ ์ ์๋ ํ์์ 'Dirty Read'๋ผ๊ณ ํ๋ฉฐ, ์ด๋ฐ ๊ฒฝ์ฐ์ ๋ฐ์ดํฐ๊ฐ ๋ํ๋ฌ๋ค๊ฐ ์ฌ๋ผ์ก๋ค๊ฐ ํ๋ ํ์์ ์ด๋ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ์ ์ ํฉ์ฑ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์ฌ๋งํ๋ฉด read uncommitted์ ๊ฒฝ์ฐ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข๋ค.
๐ฌ READ COMMITTED
์ค๋ผํด์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒฉ๋ฆฌ ์์ค์ด๋ฉฐ, Dirty Read๊ฐ ํด๊ฒฐ๋ ๊ฒฉ๋ฆฌ ์์ค์ด๋ค.
๋ค๋ฅธ ํธ๋์ญ์
์ ์ํด ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋๋ผ๋ Commit์ด ์๋ฃ๋ ๋ฐ์ดํฐ๋ง ์กฐํ๊ฐ ๊ฐ๋ฅํ๋ค.
์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด, ๊ธฐ์กด์ 1๋ฒ ๋ ์ฝ๋๋ name = hello์๊ณ , ์ด์ ๋ํด์ 'hi'๋ผ๊ณ ์
๋ฐ์ดํธ๋ฅผ ํ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด๋ ์ฌ์ฉ์ B๊ฐ 1๋ฒ ๋ ์ฝ๋์ ๋ํด์ ์กฐํํ ๋, ํ
์ด๋ธ์ด ์๋ ์
๋ฐ์ดํธ ์ ์ธ๋ ๋ก๊ทธ์ ์ ์ฅํ๋ ๊ฐ์ ์ฝ์ด์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ์
๋ฐ์ดํธ ๋๊ธฐ ์ ๋ฐ์ดํฐ๊ฐ ๋ฐํ๋๋ฉฐ, ์ถํ ์ปค๋ฐ์ด ๋์ด์ผ ์์ ํ๊ฒ ๋ฐ์์ด ์๋ฃ๋๋ค.
์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ง ์ฝ๊ธฐ ๋๋ฌธ์ '์์
์ด ์๋ฃ๋์ง ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋๋ค'๋ Dirty Read๋ ํด๊ฒฐ๋์์ง๋ง, ํ๋์ ํธ๋์ญ์
์์ SELECT ์ ํญ์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๊ฒ์ด ์๋ UPDATE ์ด์ ์ ๋ฐ์ดํฐ์ ์ดํ์ ๋ฐ์ดํฐ๊ฐ ๋ค๋ฅธ ๋ฐ์ดํฐ๊ฐ ๋ฐํ๋๊ธฐ ๋๋ฌธ์ 'Non-Repeatable Read'๊ฐ ๋ฐ์ํ๋ค.
๋จ์ํ ์น ์๋น์ค์์ ์ด๋ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋์ง ์์ง๋ง, ํ๋์ ํธ๋์ญ์
์์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๋ฒ ์ฝ๊ณ ์ฐ๋ ์์
์ด ๊ธ์ ํ์์ ๊ด๋ จ์ด ๋๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ํนํ, ์
-์ถ๊ธ ๋ก์ง์ ์๊ฐํด๋ณด์. ์ฒ์์ 10000์์ด ์กฐํ๋์ด์ 1000์์ ์ถ๊ฐํ๊ณ 11000์์ด ๋์ค๊ธธ ๊ธฐ๋ํ๋๋ฐ, ๋ค์ ์กฐํํ๋ 6000์์ผ๋ก ๋์จ๋ค๋ฉด ๋งค์ฐ ๋นํน์ค๋ฌ์ธ ๊ฒ์ด๋ค.
์ฐธ๊ณ ๋ก, ํธ๋์ญ์
๋ด๋ถ์์ ์คํ๋๋ SELECT ๋ฌธ๊ณผ ์ธ๋ถ์์ ์คํ๋๋ SELECT๋ฌธ์ ์ฐจ์ด๋ ์๋ค.
ํ์ง๋ง, Repeatable-Read์์๋ SELECT๊น์ง ํธ๋์ญ์
๋ฒ์ ๋ด์์๋ง ์๋ํ์ฌ ๊ณ์ ๋์ผํ ๊ฒฐ๊ณผ๋ง ๋ณด์ด๋๋ก ๋ง๋ค๊ฒ ๋๋ค. ์ด์ ๋ํด์๋ ์๋์์ ํ์ธํด๋ณด์.
๐ฌ REPEATABLE READ
InnoDB์์ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒฉ๋ฆฌ ์์ค์ผ๋ก, ๋ฐ์ด๋๋ฆฌ ๋ก๊ทธ๋ฅผ ๊ฐ์ง MySQL ์๋ฒ์์๋ ์ต์ Repeatable read ์ด์์ ๊ฒฉ๋ฆฌ ์์ค์ ๊ฐ์ ธ์ผ ํ๋ค. innoDB์์๋ MVCC๋ฅผ ํ์ฉํ์ฌ ๋ณ๊ฒฝ ์ ๋ ์ฝ๋๋ฅผ ์ธ๋ ๊ณต๊ฐ์ ๋ฐฑ์
ํด๋๊ณ , ์ค์ ๋ ์ฝ๋ ๊ฐ์ ๋ณ๊ฒฝํ๋๋ฐ ์ด MVCC๋ฅผ ํ์ฉํ์ฌ ๋์ผํ ํธ๋์ญ์
์์๋ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋๋ก ๋ณด์ฅํ๋ค.
๊ทผ๋ฐ ์์ ๋ดค๋ Read Committed ์ญ์ ์ธ๋ ๋ก๊ทธ์ ์๋ ๊ฐ์ ๋ณด์ฌ์คฌ์๋๋ฐ, repeatable read์ ๋ญ๊ฐ ๋ค๋ฅธ ๊ฒ์ผ๊น?
์ด๋, ์ธ๋ ์์ญ์ ๋ฐฑ์
๋ ๊ฐ ์ค ๋ช ๋ฒ์งธ ์ด์ ๊น์ง ์ฐพ์ ๋ค์ด๊ฐ๋์ง์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค.
์ธ๋ ์์ญ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ๊ฒฝ์ ๋ฐ์์ํจ ํธ๋์ญ์
์ ๋ฒํธ๋ ํจ๊ป ์ ์ฅํด๋๋ค. innoDB๋ ๋ถํ์ํ๋ค๊ณ ํ๋จํ๋ ์์ ์ ๊ณผ๊ฑฐ์ ์ธ๋ ๋ก๊ทธ๋ฅผ ์ ๊ฑฐํ๋๋ฐ, ์ด๋ ํ์ฌ ์คํ ์ค์ธ ํธ๋์ญ์
์ค ๊ฐ์ฅ ์ค๋๋ ํธ๋์ญ์
๋ฒํธ๋ณด๋ค ์์ ์ธ๋ ์์ญ์ ๋ฐ์ดํฐ๋ ์ ๊ฑฐ๊ฐ ๋ถ๊ฐ๋ฅํ๋ค. ์ ํํ๊ฒ๋, ํน์ ํธ๋์ญ์
๊ตฌ๊ฐ ๋ด์์ ๋ฐฑ์
๋ ์ธ๋ ๋ฐ์ดํฐ๊ฐ ๋ณด์กด๋์ด์ผ ํ๋ค.
๊ทธ๋ฆผ์ด ๋๋ฌด ์๋๋ก ๊ธธ์ด์ ธ์ ์์์ผ๋ก ์ชผ๊ฐฐ๋ค.
๋จผ์ , ์ฌ์ฉ์ B๊ฐ ํธ๋์ญ์
์ ์์ํ๊ธฐ ์ ์ id = 1, name = hello์ธ ๋ ์ฝ๋์ id = 2, name = journey์ธ ๋ ์ฝ๋๊ฐ ์กด์ฌํ๋ค.
์ด๋ select๋ฅผ ํตํด ์กฐํํ์ ๋ name = hello๋ฅผ ์กฐํํ์๋ค.
์ดํ, ํธ๋์ญ์
์์ด๋ 12๋ฒ์ด update๋ฅผ ํตํด์ id = 1์ ๋ ์ฝ๋์ name์ hi๋ก ๋ณ๊ฒฝํ์๊ณ , ๋ณ๊ฒฝ ์ ์ฌํญ์ ๋ํด ์ธ๋ ๋ก๊ทธ์ ๊ธฐ๋กํ์๋ค. ์ด๋, ์ธ๋ ๋ก๊ทธ์๋ ๋ณ๊ฒฝ ์ ํธ๋์ญ์
์์ด๋์ธ 6๋ฒ๋ ํจ๊ป ๊ธฐ๋ก๋์ด ์๋ค.
์ฌ์ฉ์ B๊ฐ ๋ค์ id = 1์ ๋ํด ์กฐํ๋ฅผ ํ์ ๋ ์ธ๋ ๋ก๊ทธ์ ๋ํ ์ ๋ณด๋ฅผ ํ์ธํ๋๋ฐ, ์ด๋ ์ฌ์ฉ์ B์ ํธ๋์ญ์
์์ด๋์ธ 10๋ณด๋ค ์์ ์ธ๋ ๋ก๊ทธ์ ๊ฐ์ ํ์ธํ์ฌ ์กฐํํ๊ฒ ๋๋ค. ๋๋ถ์ ์
๋ฐ์ดํธ๊ฐ ๋๋ ์ ๋๋ ํญ์ ๊ฐ์ name = hello์ ๊ฐ์ ์ฝ์ด์ฌ ์ ์๊ฒ ๋๋ค.
์ ๊ฒฝ์ฐ๋ ์์ ๋ฅผ ๋จ์ํํ๊ธฐ ์ํด์ ์ธ๋ ์์ญ์ ๋ฐ์ดํฐ๊ฐ ํ๋์ง๋ง, ๋น์ฐํ ์ฌ๋ฌ ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ ์ ์๋ค. ํธ๋์ญ์
์ด ๊ธธ์ด์ง๋ฉด ๊ธธ์ด์ง์๋ก ์ธ๋ ์์ญ์ ๋ฐ์ดํฐ ์ญ์ ๊ณ์ ๋์ด๋ ์ ์๊ธฐ ๋๋ฌธ์ MySQL ์๋ฒ ์ฑ๋ฅ์๋ ์ํฅ์ ๋ผ์น๋ค๋ ๊ฒ์ ์ฃผ์ํ์.
ํ์ง๋ง, ์ด ์ญ์ ๋ถ์ ํฉ์ด ๋ฐ์ํ ์ ์๋ค.
์ฒ์ SELECT์์๋ journey๋ง ๋ฐ์์ค์ง๋ง, ๋ ๋ฒ์งธ SELECT์์ journey์ cat์ ๋ฐ์์๋ค.
์ด๋ ๊ฒ ๋ค๋ฅธ ํธ๋์ญ์
์ ์ํํ ๋ณ๊ฒฝ ์์
์ ์ํด ๋ ์ฝ๋๊ฐ ๋ณด์๋ค ์ ๋ณด์๋ค ํ๋ ํ์์ 'Phantom Read' ๋ผ๊ณ ํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก select ... for update๋ ์ฐ๊ธฐ ๋ฝ์ ๊ฑธ์ด์ผ ํ๋๋ฐ, ์ธ๋ ๋ก๊ทธ์๋ ๋ฝ์ ๊ฑธ ์ ์๊ธฐ ๋๋ฌธ์ select ... for update๋ select ... lock in share mode๋ก ์กฐํ๋๋ ๋ ์ฝ๋๋ ๋ณ๊ฒฝ ์ ๋ฐ์ดํฐ๊ฐ ์๋ ํ์ฌ ๋ ์ฝ๋์ ๊ฐ์ ๊ฐ์ ธ์ค๊ฒ ๋๋ค.
- select for update๋ ํน์ ๋ ์ฝ๋์ ๋ํด์ X-Lock์ ๊ฑฐ๋ ๊ตฌ๋ฌธ์ด๊ณ (์
๋ฐ์ดํธ๋ฅผ ์ํด์ ๋ฒ ํ ๋ฝ์ ๊ฑฐ๋ ๋๋), select lock in share mode๋ S-Lock์ ๊ฑฐ๋ ๊ตฌ๋ฌธ์ด๋ค.
๐ก Non-Repeatable Read๋ ๋๊ฐ์ ๊ฑฐ ์๋๊น?
์ฌ๊ธฐ์ '๊ฒฐ๊ณผ์ ์งํฉ์ด ๋ค๋ฅด๊ฒ ๋์๋ค'๋ ์ ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถฐ์ผ ํ๋ค. non-repeatable read์ ๊ฒฝ์ฐ 1๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์ค์ง๋ง, ์ ๋ฐ์ดํธ๋ก ์ธํด์ hello, hi๋ผ๋ 2๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์๊ณ , ์ฌ๊ธฐ์์๋ journey์ journey, cat์ด๋ผ๋ 2๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค.
๋์ผํ ํธ๋์ญ์ ๋ด์์ ๋์ผํ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋๋ผ๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ป๋๋ค๋ ๊ฒ non-repeatable read์ด๊ณ , ๋ค๋ฅธ ๊ฒฐ๊ณผ ์งํฉ์ ์ป์ ์ ์๋ค๋ ๊ฒ phantom-read์ด๋ค. non-repeatable read์ ๊ฒฝ์ฐ ์์ ๋ ๋ฐ์ดํฐ์ ๋ํ ์ผ๊ด์ฑ ๋ฌธ์ ๋ฅผ, phantom read์ ๊ฒฝ์ฐ ์ฝ์ ์ด๋ ์ญ์ ๋ ๋ฐ์ดํฐ์ ๋ํ ์ผ๊ด์ฑ ๋ฌธ์ ๋ฅผ ๊ฐ์ง๋ค.
๐ก InnoDB์์๋ ์ Phantom Read๊ฐ ๋ฐ์ํ์ง ์์๊น?
์ง๋ ํฌ์คํ ์์ ๋ดค๋ฏ์ด, innoDB์์ ์ ๊ณตํ๋ ๋ฝ ์ค์์ '๋ ์ฝ๋ ๋ฝ'๊ณผ '๊ฐญ ๋ฝ'์ ํฉ์น '๋ฅ์คํธ ํค ๋ฝ'์ ์ ๊ณตํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
์์ ๊ฐ์ด ์ฌ์ฉ์ B์ ํธ๋์ญ์
์ด ์ปค๋ฐ๋๊ธฐ ์ ์ select ์ ๋ฝ์ ์ก๊ณ ์์ด์ ๊ณ์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
โญ๏ธ ํ์ง๋ง, select ์ดํ select for update๋ก ์กฐํํ๊ฒ ๋๋ค๋ฉด ์ธ๋ ์์ญ์ด ์๋ ์๋ณธ ํ
์ด๋ธ์ ๊ฐ์ ๋ฐ์์ค๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ์ ๋ถ์ ํฉ์ด ๋ฐ์ํ๋ค. ์ฆ, innoDB์์ phantom read๊ฐ ๋ฌด์กฐ๊ฑด ๋ฐ์ํ์ง ์๋ ๊ฒ์ ์๋๋ค! select for update์ ๊ฒฝ์ฐ ๋ฐ์ํ ์ ์๋ค.
๐ฌ SERIALIZABLE
๊ฐ์ฅ ๋จ์ํ๋ฉด์๋ ์๊ฒฉํ ๊ฒฉ๋ฆฌ ์์ค์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ๊ฒฉ๋ฆฌ ์์ค๋ณด๋ค ๋์์ฑ ์์
์ด ๋จ์ด์ง๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก innoDB ํ
์ด๋ธ์์ ์์ํ select ์์
์ ๋ฝ ์์ด๋ ์ํ๋์ง๋ง, serializable์์๋ ์ฝ๊ธฐ์ ๋ํด์๋ S-Lock์ ๊ฑธ์ด์ผ ํ๋ฉฐ, ๋ค๋ฅธ ํธ๋์ญ์
์์๋ ํด๋น ๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ๋๋ค. ์ด ๋๋ถ์ Phantom read ํ์์ด ๋ฐ์ํ์ง๋ ์์ง๋ง, innoDB์์๋ Gap Lock๊ณผ Next Key Lock ๋๋ถ์ repeatable read์์๋ phantom read๊ฐ ๋ฐ์ํ์ง ์์์ ๊ตณ์ด ์ฌ์ฉํ ํ์๊ฐ ์๋ค.
์ฝ๋ ๋ ๋ฒจ๋ก ์ ๊ฒฉ๋ฆฌ ์์ค์ ํ์ธํ๊ณ ์ถ๋ค๋ฉด ์๋ ํฌ์คํ
์ ํ์ธํด ์ฃผ์ธ์ ๐
[MySQL] ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค์ ์ฟผ๋ฆฌ๋ฅผ ํตํด ์ง์ ํ
์คํธํด๋ณด๊ธฐ