ยซ   2026/03   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Recent Posts
03-20 19:16

Today
Total

Recent Comments
๊ด€๋ฆฌ ๋ฉ”๋‰ด

์—ฐ์˜ ๊ธฐ๋ก ๐Ÿช

์ฟผ๋ฆฌ ๋™์‹œ์„ฑ ๊ฒ€์ฆ (Mysql) ๋ณธ๋ฌธ

Computer Science/๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

์ฟผ๋ฆฌ ๋™์‹œ์„ฑ ๊ฒ€์ฆ (Mysql)

kite707 2025. 10. 29. 16:45

์•„๋ž˜ ์ฟผ๋ฆฌ๊ฐ€ ์›์ž์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•ด๋ณด์ž. InnoDB ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋Š” MySQL์ด๋ผ๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

UPDATE tmp SET cnt = cnt+1 WHERE id = 1;

์ฟผ๋ฆฌ๊ฐ€ ์›์ž์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์ฟผ๋ฆฌ๊ฐ€ ์ชผ๊ฐœ์ง€์ง€ ์•Š๋Š”์ง€๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰ ์œ„์˜ ์ฟผ๋ฆฌ์—์„œ๋Š” cnt๊ฐ€ 1 ์ฆ๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ „ํ˜€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š๋Š”์ง€๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค.

 

1) ํ…Œ์ŠคํŠธ ์ค€๋น„

์•„๋ž˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด ๊ฐ„๋‹จํ•œ ํ…Œ์ด๋ธ”๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•œ๋‹ค.

CREATE TABLE tmp (
  id INT PRIMARY KEY,
  cnt INT NOT NULL DEFAULT 0
) ENGINE=InnoDB;

INSERT INTO tmp VALUES (1, 0), (2, 0);

 

2) ์ด๋ก ์  ๊ฒ€์ฆ

๋จผ์ € InnoDB์—์„œ๋Š” ์—…๋ฐ์ดํŠธ ๋˜๋Š” ํ–‰์— exclusive lock(๋ฐฐํƒ€์  ์ž ๊ธˆ)์„ ๊ฑด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋™์‹œ์— ํ–‰์„ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค. ์ด ๋ฝ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ๋Œ€๊ธฐํ•˜๊ฑฐ๋‚˜ ๋ฐ๋“œ๋ฝ์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ์ด ๋‚ด์šฉ์€ 3๋ฒˆ์—์„œ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

์ž ๊ธˆ ์ข…๋ฅ˜

Exclusive Lock(X-Lock) : ๋‚˜๋ฅผ ์ œ์™ธํ•˜๊ณ  ์“ฐ๊ธฐ/์ฝ๊ธฐ ๋‘˜๋‹ค ๋ถˆ๊ฐ€
Shared Lock(S-Lock) : ๋‚˜๋ฅผ ์ œ์™ธํ•˜๊ณ  ์“ฐ๊ธฐ ๋ถˆ๊ฐ€(์ฝ๊ธฐ๋Š” ๊ฐ€๋Šฅ)

InnoDB๋Š” ๋ฒ„ํผ ํ’€์ด๋ผ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ด ์žˆ๋‹ค. ํ•ด๋‹น ๊ณต๊ฐ„์— ๊ฐ’์„ ์บ์‹ฑํ•ด์™€์„œ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น row์— ๋ฝ์„ ๊ฑธ๊ณ (๋ฝ ๋ฏธํš๋“์‹œ ๋Œ€๊ธฐ), ๋ฒ„ํผ ํ’€์—์„œ ๊ฐ’์„ ๋ณ€ํ™”์‹œํ‚จ๋‹ค. ๋˜ํ•œ Crash๋ฅผ ๋Œ€๋น„ํ•ด redo log์— ๊ธฐ๋กํ•œ๋‹ค.

-- redo log ์˜ˆ์‹œ
Row id=1: cnt 0 -> 1

๊ทธ๋ฆฌ๊ณ  ์ปค๋ฐ‹ ์‹œ์ ์— ๋””์Šคํฌ์— ๋ณ€๊ฒฝ๋‚ด์šฉ์„ ๋ฐ˜์˜ํ•œ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ์ด๋ก ์ ์œผ๋กœ ์œ„ ์ฟผ๋ฆฌ๋Š” ์›์ž์ ์ด๋‹ค. InnoDB๋Š” ํ–‰ ๋‹จ์œ„๋กœ ๋ฝ์„ ๊ฑธ๊ณ  ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ์— ํ–‰์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ๋ชปํ•˜๊ฒŒ ๋ง‰๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

3) DB ์—”์ง„ ๋ ˆ๋ฒจ ํ…Œ์ŠคํŠธ

์ด์ œ ์•„๋ž˜ 3๊ฐ€์ง€ ์ƒํ™ฉ์— ๋Œ€ํ•ด ํ•ด๋‹น ์ฟผ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€ํ•œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋„๋ก ํ•˜์ž.

  1. ๋‹จ์ผ ์ฟผ๋ฆฌ ์‹คํ–‰ → Update๋ฌธ ๋ฐ˜์˜
  2. ๋‘ ์„ธ์…˜์—์„œ ๊ฐ™์€ ํ–‰ ์—…๋ฐ์ดํŠธ ์‹œ๋„ → row-level lock์ด ๊ฑธ๋ ค ๋Šฆ๊ฒŒ ์ˆ˜ํ–‰ํ•œ ์ฟผ๋ฆฌ ๋Œ€๊ธฐ
  3. ๋ฐ๋“œ๋ฝ ์ƒํ™ฉ → ๋ฐ๋“œ๋ฝ ๊ฐ์ง€ ๋ฐ ์„ธ์…˜ ํ‚ฌ&๋กค๋ฐฑ ํ›„ ์ฟผ๋ฆฌ ์ˆ˜ํ–‰

๋จผ์ € 1๋ฒˆ ์ƒํ™ฉ์— ๋Œ€ํ•ด ์•„๋ž˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

UPDATE tmp SET cnt = cnt + 2 WHERE id = 1;

cnt๊ฐ€ 2 ์ฆ๊ฐ€ํ–ˆ๋‹ค๋ฉด ๊ธฐ๋Œ€ํ•œ๋Œ€๋กœ ๋™์ž‘ํ•œ ๊ฒƒ์ด๋‹ค.

์ด์ œ 2๋ฒˆ ์ƒํ™ฉ์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ์„ธ์…˜ 1์ด ์ปค๋ฐ‹๋  ๋•Œ ๊นŒ์ง€ ์„ธ์…˜ 2๊ฐ€ ๋Œ€๊ธฐํ•˜๋ฉด ๋œ๋‹ค.

-- ์„ธ์…˜ 1์—์„œ ์ˆ˜ํ–‰
START TRANSACTION;
UPDATE tmp SET cnt = cnt + 2 WHERE id = 1;

-- ์„ธ์…˜ 2์—์„œ ์ˆ˜ํ–‰
START TRANSACTION;
UPDATE tmp SET cnt = cnt + 1 WHERE id = 1; -- ๋Œ€๊ธฐ

์ด๋•Œ show processlist; ๋ฅผ ํ†ตํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ์—…๋ฐ์ดํŠธ๊ฐ€ ์‹คํ–‰๋˜์ง€ ๋ชปํ•˜๊ณ  updating์ƒํƒœ์— ๋จธ๋ฌผ๋Ÿฌ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 

3๋ฒˆ ์ƒํ™ฉ์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. InnoDB๋Š” ๋ฐ๋“œ๋ฝ์„ ๊ฐ์ง€ํ•˜๋ฉด ๋‚ด๋ถ€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋”ฐ๋ผ Killํ•  ์„ธ์…˜์„ ์„ ํƒํ•˜๊ณ (๋กค๋ฐฑ ๋น„์šฉ, ํŠธ๋žœ์žญ์…˜ ID ๋“ฑ ๊ณ ๋ ค) ํ•ด๋‹น ์„ธ์…˜์˜ ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑ ๋ฐ ๋ฝ์„ ํ•ด์ œํ•œ๋‹ค. ์ฆ‰ ๋ฐ๋“œ๋ฝ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์„ธ์…˜์„ Kill ๋ฐ ๋กค๋ฐฑํ•˜์—ฌ ๋ฐ๋“œ๋ฝ์„ ํ•ด์†Œํ•˜๊ณ , ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ์„ฑ๊ณต์ด๋‹ค.

-- ์„ธ์…˜1
START TRANSACTION;
UPDATE tmp SET cnt = cnt + 2 WHERE id = 1;

-- ์„ธ์…˜2
START TRANSACTION;
UPDATE tmp SET cnt = cnt + 1 WHERE id = 2;
UPDATE tmp SET cnt = cnt + 1 WHERE id = 1;

--์„ธ์…˜1
-- ERROR 1213 (40001): Deadlock found when trying to get lock; 
-- try restarting transaction 
UPDATE tmp SET cnt = cnt + 2 WHERE id = 2; -- ๋ฐ๋“œ๋ฝ ๋ฐœ์ƒ

-- ์„ธ์…˜ 1
COMMIT;

-- ์„ธ์…˜ 2 
COMMIT;

์ด ์ƒํ™ฉ์„ ๊ทธ๋ฆผ๊ณผ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค. ์–ด๋–ค ์„ธ์…˜์„ Killํ• ์ง€๋Š” ๋‚ด๋ถ€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค.

 

4) ๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ

์ด์ œ DB ๋ ˆ๋ฒจ์—์„œ ๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋„๋ก ํ•˜์ž.

๋จผ์ € ๊ฐ„๋‹จํ•˜๊ฒŒ mysqlslap์„ ์ด์šฉํ•ด ์ฟผ๋ฆฌ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

mysqlslap --host=127.0.0.1 --port=3306 --user=root --password=<์‹ค์ œ๋น„๋ฐ€๋ฒˆํ˜ธ> \\
--concurrency=100 --iterations=10 \\
--query="UPDATE tmp SET cnt = cnt + 1 WHERE id =1;" \\
--create-schema=backend_basic

1000์ด ์‹ค์ œ๋กœ ์ฆ๊ฐ€ํ–ˆ๋‹ค๋ฉด ์„ฑ๊ณต์ด๋‹ค. 

๋˜ํ•œ SHOW ENGINE INNODB STATUS\G ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ๋ฐ๋“œ๋ฝ ์—ฌ๋ถ€๋‚˜ Lock ๋Œ€๊ธฐ ์—ฌ๋ถ€ ๋“ฑ๋„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜๋Š” INNODB ๋‚ด๋ถ€ ์ƒํƒœ ๋กœ๊ทธ๋ฅผ ๋ฐœ์ทŒํ•œ ๊ฒƒ์ด๋‹ค.

=====================================
2025-10-28 14:27:30 281472164945664 INNODB MONITOR OUTPUT
=====================================
. . . ์ค‘๋žต . . . 
------------
TRANSACTIONS
------------
Trx id counter 11539
Purge done for trx's n:o < 11539 undo n:o < 0 state: running but idle
History list length 1
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 562947761801648, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 562947761800840, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 11536, ACTIVE 28 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1128, 2 row lock(s), undo log entries 1
MySQL thread id 10, OS thread handle 281472163827456, query id 115 192.168.65.1 root updating
/* ApplicationName=DataGrip 2022.3.3 */ UPDATE tmp SET cnt = cnt + 1 WHERE id = 1
------- TRX HAS BEEN WAITING 5 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 57 page no 4 n bits 72 index PRIMARY of table `backend_basic`.`tmp` trx id 11536 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 000000002d0f; asc     - ;;
 2: len 7; hex 02000001522946; asc     R)F;;
 3: len 4; hex 800003ea; asc     ;;

------------------
---TRANSACTION 11535, ACTIVE 32 sec
2 lock struct(s), heap size 1128, 2 row lock(s), undo log entries 1
MySQL thread id 9, OS thread handle 281472164945664, query id 124 192.168.65.1 root starting
/* ApplicationName=DataGrip 2022.3.3 */ SHOW ENGINE INNODB STATUS
--------
FILE I/O
--------
. . . ์ดํ•˜ ์ƒ๋žต

์—ฌ๊ธฐ์„œ ํŠธ๋žœ์žญ์…˜ ๋ถ€๋ถ„์„ ์ข€ ๋” ๋ณด๋„๋ก ํ•˜์ž.

๋จผ์ € ํŠธ๋žœ์žญ์…˜ 11536์€ 28์ดˆ์งธ ์‹คํ–‰์ค‘์ด๋‹ค. ๋˜ํ•œ ------- TRX HAS BEEN WAITING 5 SEC FOR THIS LOCK TO BE GRANTED: ๋ถ€๋ถ„์„ ๋ณด๋ฉด ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ๋ฝ์„ ์–ป๊ธฐ ์œ„ํ•ด 5์ดˆ์งธ ๋Œ€๊ธฐ์ค‘์ด๋ผ๋Š” ๋œป์ด๋‹ค.

---TRANSACTION 11536, ACTIVE 28 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1128, 2 row lock(s), undo log entries 1
MySQL thread id 10, OS thread handle 281472163827456, query id 115 192.168.65.1 root updating
/* ApplicationName=DataGrip 2022.3.3 */ UPDATE tmp SET cnt = cnt + 1 WHERE id = 1
------- TRX HAS BEEN WAITING 5 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 57 page no 4 n bits 72 index PRIMARY of table `backend_basic`.`tmp` trx id 11536 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 000000002d0f; asc     - ;;
 2: len 7; hex 02000001522946; asc     R)F;;
 3: len 4; hex 800003ea; asc     ;;