ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

MySQL MDL(metadata_locks): insert ์ฟผ๋ฆฌ๊ฐ€ ๋ณ‘๋ชฉ ์ƒํƒœ์— ๋น ์ง€๋Š” ์ด์œ  ๊ธ€์—์„œ ์ด์–ด์ง€๋Š” ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
์ด ๊ธ€์€ MySQL InnoDB ์—”์ง„ ๊ธฐ์ค€์œผ๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

์ด์ „ ๊ธ€์—์„œ MySQL MDL(metadata_locks)๋กœ ์ธํ•ด์„œ ์˜๋„์น˜ ์•Š๊ฒŒ insert ์ฟผ๋ฆฌ๊ฐ€ ๋ณ‘๋ชฉ ์ƒํƒœ์— ๋น ์กŒ์—ˆ๋Š”๋ฐ์š” ๐Ÿฅฒ
์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์žฌ๋ฐœ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด์„œ Observability๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ธฐ๋กํ•ด๋ณด๋ ค๊ณ  ํ•ด์š”.

๋จผ์ €, MDL์— ๋Œ€ํ•ด์„œ ์ •ํ™•ํžˆ ์ดํ•ดํ•ด์•ผ ์ ์ ˆํ•œ metric์„ ๋ฝ‘์•„์„œ ํšจ์œจ์ ์œผ๋กœ Observability๋ฅผ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”.
๊ทธ๋ž˜์„œ Metadata Lock(MDL)์— ๋Œ€ํ•ด์„œ ์ข€ ๋” ์•Œ์•„๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

MySQL Metadata Lock(MDL) ์ดํ•ดํ•˜๊ธฐ

MySQL์€ ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ณ  ๋™์‹œ ์ ‘๊ทผ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ๋ฝ์„ ์‚ฌ์šฉํ•ด์š”.
๊ทธ์ค‘ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ฝ(Metadata Lock, MDL)์€ ํ…Œ์ด๋ธ”์ด๋‚˜ ์Šคํ‚ค๋งˆ ๊ตฌ์กฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณดํ˜ธํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
MDL์€ ํ…Œ์ด๋ธ”์„ ์ฝ๊ฑฐ๋‚˜ ์“ฐ๋Š” ๊ฒฝ์šฐ, ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ์ž๋™์œผ๋กœ ํš๋“๋ฉ๋‹ˆ๋‹ค.

fyi; ์œ„์—์„œ ์ด์•ผ๊ธฐํ–ˆ๋“ฏ์ด MDL์€ MySQL์—์„œ  ํ…Œ์ด๋ธ”์ด๋‚˜ ์Šคํ‚ค๋งˆ ๊ตฌ์กฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
์ด๋Ÿฐ Lock ๊ฐœ๋…์€ ์—ฌ๋Ÿฌ ์š”์ฒญ์ด ๋™์‹œ์— ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” ์‹œ์Šคํ…œ(=๋™์‹œ ์ฒ˜๋ฆฌ ์‹œ์Šคํ…œ)์—์„œ ํ™œ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ์š”,
๋™์‹œ ์ฒ˜๋ฆฌ ์‹œ์Šคํ…œ์—์„œ ๋ฌด๊ฒฐ์„ฑ์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ, ํ•ญ์ƒ ๊ฒฝ์Ÿ ์กฐ๊ฑด(=race condition)์„ ๊ณ ๋ คํ•ด์•ผ ํ•˜๊ณ  ์ด ๋•Œ lock ๊ฐœ๋…์„ ํ™œ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๊ฝค ์žˆ์Šต๋‹ˆ๋‹ค.

 

Metadata Lock ์œ ํ˜•

MySQL InnoDB์—์„œ Lock์€ ์—ฌ๋Ÿฌ ์œ ํ˜•์œผ๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ ๊ณ„์ธต์ ์œผ๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  Metadata Lock์—๋„ ๊ฐ™์€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ํ™œ์šฉ๋ผ์š”.

์ผ๋ฐ˜์ ์œผ๋กœ Lock์€ ์ ์œ ํ•˜๋Š” ๊ฐœ๋…์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ณผ๋„ํ•˜๊ฒŒ ์ƒ์„ฑ๋˜๋ฉด ์„ฑ๋Šฅ ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ทธ๋ž˜์„œ ๋™์‹œ์„ฑ์ด ๋†’์€ ํ™˜๊ฒฝ์—์„œ๋Š” ์ด๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. 

MySQL์—์„œ๋Š” ์„ฑ๋Šฅ์„ ์ตœ๋Œ€ํ•œ์œผ๋กœ ๋Œ์–ด๋‚ด๊ธฐ ์œ„ํ•ด MDL์„ ๊ณ„์ธต์ ์œผ๋กœ ๋ถ„๋ฅ˜ํ•ด์„œ ํ™œ์šฉํ•ด์š”.

Metadata Lock์˜ ์œ ํ˜•๊ณผ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • MDL_SHARED(=Shared Lock)
    • Shared Lock์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์ด ๋™์‹œ์— ํš๋“ํ•  ์ˆ˜ ์žˆ๊ณ  ๋™์‹œ์„ฑ ํ™•๋ณด๊ฐ€ ๊ฐ€๋Šฅํ•ด์š”. 
    • ์ฃผ๋กœ SELECT, INSERT ์™€ ๊ฐ™์ด ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” MDL์— ๊ฒฝ์šฐ Shared Lock์„ ํš๋“ํ•˜๊ฒŒ ๋ผ์š”.
    • ์„ธ๋ถ€์ ์œผ๋กœ๋Š” ๊ฐ๊ฐ ์•ก์…˜์— ๋”ฐ๋ผ MDL_SHARED_READ, MDL_SHARED_WRITE ๋“ฑ ์œผ๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ์–ด์š”.
  • MDL_EXCLUSIVE(=Exclusive Lock)
    • Exclusive Lock์€ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์—๋งŒ ํš๋“ ๊ฐ€๋Šฅํ•œ Lock์ด์—์š”. ์—ฌ๋Ÿฌ ํŠธ๋žœ์žญ์…˜์—์„œ ํ•ด๋‹น Lock์„ ํš๋“ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด, ๋‹จ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜๋งŒ Lock ํš๋“์— ์„ฑ๊ณตํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” Lock์ด ๋ฐ˜ํ™˜๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ ธ์š”.
    • ๋˜ํ•œ, Exclusive Lock์€ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•ด ์–ด๋– ํ•œ Lock๋„ ๊ฑธ๋ ค์žˆ์ง€ ์•Š์•„์•ผ ํš๋“ ๊ฐ€๋Šฅํ•ด์š”. ๊ทธ๋ž˜์„œ ๋งŒ์•ฝ Shared Lock์„ ์˜ค๋ž˜ ์žก๊ณ  ์žˆ๋Š” ํŠธ๋žœ์žญ์…˜์ด ์žˆ๋‹ค๋ฉด, ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ Exclusive Lock์„ ํš๋“ํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋Œ€๊ธฐํ•˜๊ฒŒ ๋ผ์š”.
    • ALTER TABLE๊ณผ ๊ฐ™์€ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ ๋ณ€๊ฒฝํ•˜๋Š” DDL ์ž‘์—… ์‹œ ํš๋“ํ•˜๊ฒŒ ๋ผ์š”.
  • MDL_INTENTION(=Intention Lock)
    • Intention Lock์€ ์ž ๊ธˆ์„ ๊ฑธ๊ธฐ ์ „์— ๋จผ์ € ์˜๋„(intent)๋ฅผ ํ‘œ์‹œํ•˜์—ฌ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜๊ณผ์˜ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด InnoDB์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ž ๊ธˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด์—์š”.
    • ํŠธ๋žœ์žญ์…˜ ๊ฒฉ๋ฆฌ ๋ฐ ๋‹ค์ค‘ ํŠธ๋žœ์žญ์…˜ ๋™์‹œ ์‹คํ–‰์„ ์ตœ์ ํ™”ํ•˜๋Š” ํšจ๊ณผ๋„ ์žˆ์–ด์š”.
    • InnoDB ์—”์ง„์ด ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•˜๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ œ์–ดํ•  ์ผ์€ ๊ฑฐ์˜ ์—†์–ด์š”.

 

MDL์˜ ์œ ํ˜•๊ณผ ๋ณ‘๋ชฉ์ด ๋ ๋งŒํ•œ ๋ถ€๋ถ„์„ ์‚ดํŽด๋ดค์œผ๋‹ˆ ์ด์ œ Observability ๊ด€๋ จ ๋‚ด์šฉ์„ ์•Œ์•„๋ณผ๊ฒŒ์š”.

Observability ํ™•๋ณดํ•˜๊ธฐ

ํ˜„์žฌ ์š”๊ตฌ์‚ฌํ•ญ์œผ๋กœ๋Š” metadata lock์„ ํš๋“ํ•˜๋Š” PENDING ์ƒํƒœ๊ฐ€ ๋น„์ •์ƒ์ ์œผ๋กœ ๊ธธ๊ฒŒ ์œ ์ง€๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ฐ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด ๋ชฉํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  Observability ํ™•๋ณด๋ฅผ ์œ„ํ•œ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณผ๊ฒŒ์š”.

๊ธฐ๋ณธ์ ์œผ๋กœ MySQL InnoDB ์—”์ง„์—์„œ metadata lock ์ •๋ณด๋Š” performance_schema.metadata_locks ํ…Œ์ด๋ธ”์„ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

metadata_locks ํ…Œ์ด๋ธ”์˜ ๋Œ€ํ‘œ ์ปฌ๋Ÿผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์•„๋ž˜ ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ์„ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ œ์ผ ์ค‘์š”ํ•œ PENDING ์‹œ๊ฐ„์„ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์‹คํ–‰ ์‹œ์  ์‹œ๊ฐ„์ด ํ•„์š”ํ•œ๋ฐ, ํ•ด๋‹น ํ…Œ์ด๋ธ”๋งŒ์œผ๋กœ๋Š” ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. 
๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” performance_schema.threads ํ…Œ์ด๋ธ”์„ ์ถ”๊ฐ€๋กœ joinํ•ด์„œ ํ™œ์šฉํ•ด์•ผํ•ด์š”.
(performance_schema.threads ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ์€ ์ž์„ธํ•˜๊ฒŒ ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค)

์ปฌ๋Ÿผ๋ช… ์„ค๋ช…
OBJECT_TYPE ๋ฝ์ด ๊ฑธ๋ฆฐ OBJECT ์œ ํ˜• (TABLE, SCHEMA, FUNCTION ๋“ฑ)
OBJECT_SCHEMA
ํ•ด๋‹น OBJECT๊ฐ€ ํฌํ•จ๋œ ์Šคํ‚ค๋งˆ(=ํ…Œ์ด๋ธ”) ์ด๋ฆ„
OBJECT_NAME ๋Œ€์ƒ OBJECT ์ด๋ฆ„
LOCK_TYPE ํš๋“ํ•œ ๋ฝ ์œ ํ˜• (SHARED, SHARED_READ, SHARED_WRITE, , EXCLUSIVE ๋“ฑ)
LOCK_STATUS ๋ฝ์˜ ์ƒํƒœ (PENDING, GRANTED, TIMEOUT, KILLED ๋“ฑ)
OWNER_THREAD_ID metadata lock์„ ์š”์ฒญํ•œ thread ID
OWNER_EVENT_ID metadata lock์„ ์š”์ฒญํ•œ ์ด๋ฒคํŠธ ID

 

๊ฒฐ๋ก ์ ์œผ๋กœ ์•„๋ž˜ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด PENDING ์ƒํƒœ์ธ ์“ฐ๋ ˆ๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ 
PROCESSLIST_TIME ์ปฌ๋Ÿผ์„ ํ†ตํ•ด์„œ ๊ณผ๋„ํ•˜๊ฒŒ PENDING ์ƒํƒœ๊ฐ€ ์ง€์—ฐ๋˜๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์กฐ๊ธˆ ๊ณ ๋ฏผ๋˜๋Š” ์ ์€ PROCESSLIST_TIME์€ ์—ฌ๋Ÿฌ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์˜ ๊ฒฝ์šฐ "PENDING์ด๋ผ๋Š” ์ƒํƒœ๊ฐ€ ์ž ๊น ์ง€์†๋˜๋Š” ๋™์•ˆ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐญ์ณํ•ด์„œ ๋ฉ”ํŠธ๋ฆญ์œผ๋กœ ๋‚จ๊ฒผ๋‹ค๋ฉด, ์ด PENDING ์ƒํƒœ๊ฐ€ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค"๋Š” ์ธ๋ฐ์š”,
์ด ๊ฒฝ์šฐ๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ํˆด(e.g. datadog) ์„ ํ†ตํ•ด์„œ ๋ฉ”ํŠธ๋ฆญ์„ ์ ์ ˆํ•˜๊ฒŒ ๊ทธ๋ฃนํ•‘ํ•˜๋ฉด ์›ํ•˜๋Š” ์˜ต์ €๋ฒ„๋นŒ๋ฆฌํ‹ฐ๋ฅผ ์ถฉ์กฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”.

SELECT
    ml.OBJECT_TYPE,
    ml.OBJECT_SCHEMA,
    ml.OBJECT_NAME,
    ml.LOCK_TYPE,
    ml.LOCK_STATUS,
    t.THREAD_ID,
    t.PROCESSLIST_ID,
    t.PROCESSLIST_USER,
    t.PROCESSLIST_HOST,
    t.PROCESSLIST_DB,
    t.PROCESSLIST_TIME,
    t.PROCESSLIST_STATE,
    t.PROCESSLIST_INFO
FROM performance_schema.metadata_locks ml
LEFT JOIN performance_schema.threads t ON ml.OWNER_THREAD_ID = t.THREAD_ID
WHERE ml.LOCK_STATUS = 'PENDING'

 

๋‹ค์Œ ๊ธ€์€ ์‹ค์ œ๋กœ ์ด ์ฟผ๋ฆฌ๋กœ ์˜ต์ €๋ฒ„๋นŒ๋ฆฌํ‹ฐ๋ฅผ ํ™•๋ณดํ•ด๋ณด๊ณ  ๊ฒฝํ—˜์ด ์–ด๋• ๋Š”์ง€ ๊ณต์œ ํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋„ค์š” ใ…Žใ…Ž
๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค :)

 

References