INSERT INTO SELECT SHARED LOCK(row LOCK)

  • ๋งˆ์ผ“๋ณด๋กœ์—์„œ ์ผํ•˜๋ฉด์„œ ์ƒ๊ธด ํŠธ๋žœ์žญ์…˜ ๋ฌธ์ œ์— ๋Œ€ํ•ด ์‹œ๋‹ˆ์–ด๋‹˜๊ณผ ๊ต๋ฅ˜ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

  • ์ด ๊ธ€์€ ๋ธ”๋กœ๊ทธ๋กœ ์ด๊ด€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ 1

๋ชฉํ‘œ

  • Table๋‹จ์œ„์˜ LOCK์ด ๊ฑธ๋ฆฌ๋Š”๊ฐ€? ์•„๋‹ˆ๋ฉด ROW๋‹จ์œ„์˜ LOCK์ด ๊ฑธ๋ฆฌ๋Š”๊ฐ€? (๋ ˆ์ฝ”๋“œ ๋ฝ)

  • ROW๋‹จ์œ„: ํŠน์ • ๋ฐ์ดํ„ฐ์—๋งŒ SHARED LOCK์ด ๊ฑธ๋ฆฌ๊ณ , ๋‹ค๋ฅธ๋ฐ์ดํ„ฐ์˜ CRUD์—๋Š” ์˜ํ–ฅ์ด ์—†๋Š”๊ฐ€?

    • SHARED LOCK: ์ฝ๊ธฐ ๊ฐ€๋Šฅ. ์ˆ˜์ •/์‚ญ์ œ ๋ถˆ๊ฐ€

์‹œ๋‚˜๋ฆฌ์˜ค

  • Transaction Mode: Manual

create table test1 (
    col1 int primary key auto_increment,
    col2 char(10)
);
create table test2 select * from test1 limit 0;

insert into test1 (col2) values ('aaa'),('bbb'),('ccc');

## ํ˜„์žฌ ๊ฑธ๋ฆฐ lock ์กฐํšŒ
select * from performance_schema.data_locks

1. Session 1

  • col1=1 S๋ฝ ํš๋“ ์‹œ๋„

  • primaryKey=1 S๋ฝ ํš๋“ ์„ฑ๊ณต

begin;

insert into test2
select *
from test1
where col1 = '1';

2. Session 2

  • col1=2 X๋ฝ ํš๋“ ์‹œ๋„

  • primaryKey=2 X๋ฝ ํš๋“ ์„ฑ๊ณต

update test1
set col2 = '1111'
where col1 = 2;

3. Session 2

  • col1=1 X๋ฝ ํš๋“ ์‹œ๋„

  • ํ•˜์ง€๋งŒ Session 1 ์—์„œ S๋ฝ์„ ๊ฑธ๊ณ  ์žˆ๊ธฐ์— ํ˜ธํ™˜๋˜์ง€ ์•Š์•„ WAITING.

update test1
set col2 = '1111'
where col1 = 1;

4. Session 1 commit, Session 2 commit

๊ฒฐ๊ณผ

  • ๋ฝ์ด ๊ฑธ๋ฆฌ์ง€ ์•Š์€ ๋ ˆ์ฝ”๋“œ์—๋Š” update๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • S๋ฝ์ด ๊ฑธ๋ฆฐ ๋ ˆ์ฝ”๋“œ์— X๋ฝ์ด ๋“ค์–ด์˜ค๋ฉด S๋ฝ์ด ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

    • S๋ฝ๊ณผ X๋ฝ์€ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค.

    • timeout์˜ ์ฃผ๋ฒ”.

  • ์ฆ‰ InnoDB๋Š” ๋ ˆ์ฝ”๋“œ๋ฝ์œผ๋กœ ์›€์ง์ธ๋‹ค.

ํ•˜์ง€๋งŒ..

  • ์ •๋ฆฌํ•˜๋ฉด์„œ ์ตœ๊ทผ ์ฝ์€ REAL MySQL์˜ ์ž ๊ธˆ ํŒŒํŠธ๊ฐ€ ์ƒ๊ฐ๋‚˜์„œ ๋‹ค์‹œ ์ฝ์–ด๋ดค์Šต๋‹ˆ๋‹ค.

์ด ํ…Œ์ด๋ธ”์— ์ธ๋ฑ์Šค๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? 
์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์—๋Š” ํ…Œ์ด๋ธ”์„ ํ’€ ์Šค์บ”ํ•˜๋ฉด์„œ UPDATE ์ž‘์—…์„ํ•˜๋Š”๋ฐ, 
์ด ๊ณผ์ •์—์„œ ํ…Œ์ด๋ธ”์— ์žˆ๋Š” 30์—ฌ๋งŒ ๊ฑด์˜ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๋ฅผ ์ž ๊ทธ๊ฒŒ ๋œ๋‹ค.
์ด๊ฒƒ์ด MySQL์˜ ๋ฐฉ์‹์ด๋ฉฐ, MySQL์—์„œ ์ธ๋ฑ์Šค ์„ค๊ณ„๊ฐ€ ์ค‘์š”ํ•œ ์ด์œ  ๋˜ํ•œ ์ด๊ฒƒ์ด๋‹ค.

- REAL MySQL 1๊ถŒ. 5.3.2 ์ธ๋ฑ์Šค์™€ ์ž ๊ธˆ (172p)
  • ์ด ๋‚ด์šฉ์„ ์ฝ๊ณ  ์•ž์˜ ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ๋ณด๋‹ˆ

    • where ์กฐ๊ฑด์˜ col1์€ PK์ด๊ธฐ์— unique index๋กœ ์ด๋ฏธ ์žกํ˜€์žˆ์–ด ๋‹จ์ผ ๋ ˆ์ฝ”๋“œ๋ฝ์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.

    • ํ•˜์ง€๋งŒ index๊ฐ€ ์—†๋Š” col2๋ผ๋ฉด?

    • col2์— non unique index๋ฅผ ๊ฑธ๊ณ  ์กฐํšŒํ•œ๋‹ค๋ฉด?

ํ…Œ์ŠคํŠธ 2

๋ชฉํ‘œ

  • index๊ฐ€ ์•„๋‹Œ col2๋ฅผ where ์กฐ๊ฑด์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ๋ ˆ์ฝ”๋“œ๋ฝ์ด ์–ด๋–ป๊ฒŒ ์žกํžˆ๋Š”๊ฐ€?

์‹œ๋‚˜๋ฆฌ์˜ค

  • ์ดˆ๊ธฐ ์„ธํŒ… ๋™

1. Session 1

  • col2=bbb S๋ฝ ํš๋“ ์‹œ๋„.

  • ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ์— ๋Œ€ํ•ด S๋ฝ ํš๋“ ์„ฑ๊ณต.

begin;

insert into test2
select *
from test1
where col2 = 'bbb';

2. Session 2

  • col2=ccc X๋ฝ ํš๋“ ์‹œ๋„.

  • ํ•˜์ง€๋งŒ Session 1 ์—์„œ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ์— S๋ฝ์„ ๊ฑธ๊ณ  ์žˆ๊ธฐ์— ํ˜ธํ™˜๋˜์ง€ ์•Š์•„ WAITING.

update test1
set col2 = 'fff'
where col2 = 'ccc';

3. Session 1 commit, Session 2 commit

๊ฒฐ๊ณผ

  • index๊ฐ€ ์—†๋‹ค๋ฉด ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋ฝ์— ๊ฑธ๋ฆฐ๋‹ค.

ํ…Œ์ŠคํŠธ 3

๋ชฉํ‘œ

  • col2์— non unique index๋ฅผ ๊ฑธ๊ณ  where ์กฐ๊ฑด์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ๋ ˆ์ฝ”๋“œ๋ฝ์ด ์–ด๋–ป๊ฒŒ ์žกํžˆ๋Š”๊ฐ€?

์‹œ๋‚˜๋ฆฌ์˜ค

create table test1
(
    col1 int primary key auto_increment,
    col2 char(10)
);

create table test2
select *
from test1
limit 0;

insert into test1 (col2)
values ('aaa'), ('aaa'),
       ('bbb'), ('bbb'),
       ('ccc'), ('ccc');

create index test1_col2_index on test1(col2); ## ์ธ๋ฑ์Šค ์ƒ์„ฑ

1. Session 1

  • col2=bbb S๋ฝ ํš๋“ ์‹œ๋„

  • primaryKey=3,4,5 S๋ฝ ํš๋“ ์„ฑ๊ณต

  • col2๋Š” non unique index ์ด์ง€๋งŒ primaryKey=3,4 S๋ฝ ํš๋“ ์„ฑ๊ณต.

  • primaryKey=5๋„ S๋ฝ์ด์ž GAP๋ฝ์œผ๋กœ ํš๋“ํ–ˆ๋Š”๋ฐ ์ด๋ถ€๋ถ„์€ ์ข€ ๋” ๊ณต๋ถ€ํ•ด์•ผ๋ฉ๋‹ˆ๋‹ค.

begin;

insert into test2
select *
from test1
where col2 = 'bbb';

2. Session 2

  • col2=ccc X๋ฝ ํš๋“ ์‹œ๋„

  • primaryKey=5,6 X๋ฝ ํš๋“ ์„ฑ๊ณต

  • ๊ทผ๋ฐ unique index์ด๋˜ ๊ฒƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ REC_NOT_GAP, GAP ๋ฝ๋“ค์ด ์ถ”๊ฐ€๋กœ ํš๋“๋ฉ๋‹ˆ๋‹ค.

update test1
set col2 = 'fff'
where col2 = 'ccc';

3. Session 2

  • col2=bbb X๋ฝ ํš๋“ ์‹œ๋„

  • ํ•˜์ง€๋งŒ Session 1 ์—์„œ S๋ฝ์„ ๊ฑธ๊ณ  ์žˆ๊ธฐ์— ํ˜ธํ™˜๋˜์ง€ ์•Š์•„ WAITING.

update test1
set col2 = 'ggg'
where col2 = 'bbb';

4. Session 1 commit, Session 2 commit

๊ฒฐ๊ณผ

  • ํ…Œ์ŠคํŠธ 1๊ณผ ๊ฒฐ๊ณผ๋Š” ๊ฐ™์ง€๋งŒ ๋ฝ์ด ๊ฑธ๋ฆฌ๋Š” ํ˜•ํƒœ๊ฐ€ ๋งค์šฐ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์ตœ์ข… ๊ฒฐ๋ก 

innoDB์—์„œ unique index์— ๋Œ€ํ•œ INSERT INTO SELECT SHARED LOCK ๋Š” ๋ ˆ์ฝ”๋“œ ๋ฝ์ด ๋งž์Šต๋‹ˆ๋‹ค.

  • ํ•˜์ง€๋งŒ non unique index์˜ ๊ฒฝ์šฐ ๋ฝ์ด ๊ฑธ๋ฆฌ๋Š” ํ˜•ํƒœ๊ฐ€ ๋งค์šฐ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

    • IS, IX, ๊ฐญ ๋ฝ๋“ฑ์— ๋Œ€ํ•œ ๊ณต๋ถ€๊ฐ€ ๋ถ€์กฑํ•ด ์ •ํ™•ํžˆ ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์‹ฌ์ง€์–ด no index ์ธ ๊ฒฝ์šฐ๋Š” ์ „์ฒด ๋ ˆ์ฝ”๋“œ ๋ฝ์œผ๋กœ ํ…Œ์ด๋ธ” ๋ฝ๊ณผ ๊ฐ™์€ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‹ค๋ฌด์—์„œ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ์—†์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.

  • ์ด ์ด์Šˆ๋Š” ์ผ๋ฐ˜์ ์ด์ง€ ์•Š์€ ์—…๋ฌด ํ๋ฆ„์—์„œ ์ˆ˜๊ธฐ ์ž‘์—… ๊ฐ„ ํŠธ๋žœ์žญ์…˜ ์กฐ์ž‘์„ ์ž˜๋ชปํ•œ ์ธ์  ์‹ค์ˆ˜๊ฐ€ ๋” ํฝ๋‹ˆ๋‹ค. (์˜์—…์˜ ์š”์ฒญ)

  • ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ…Œ์ด๋ธ”์€ ์ตœ์†Œํ•œ non unique index๊ฐ€ ๊ฑธ๋ ค ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Last updated

Was this helpful?