한마디만 하면 자물쇠가 꺼져요.

15184 단어 MySQLtech
여러 개의 거래가 여러 개의 기록을 잠글 때, 사라진 자물쇠는 정해진 시간에 발생한다.
  • 트랜잭션 A 잠금 레코드 1→성공
  • 트랜잭션 B 잠금 레코드 2→성공
  • 사무 A 잠금 기록 2 → 잠금 해제 대기 2
  • 트랜잭션 B 잠금 레코드 1→잠금 해제 대기 1
  • A와 B는 모두 상대방이 로큰롤을 터뜨리기를 기다리며 자물쇠를 잠갔다.
    MySQL에서 사라진 자물쇠를 검출하면 한 거래에서 사라진 자물쇠 오류가 발생하여 거래를 강제로 중지합니다.
    예를 들어 두 개의 거래를 동시에 진행하면 잠금 오류가 발생할 수 있다.
    CREATE TABLE t (a INT, val INT, INDEX(a));
    INSERT INTO t VALUES (1,0),(2,0),(3,0),(4,0),(5,0),(6,0),(7,0),(8,0),(9,0);
    
    트랜잭션 A
    BEGIN;
    UPDATE t SET val=0 WHERE a=1;  # レコード1をロック
    UPDATE t SET val=0 WHERE a=9;  # レコード9をロック
    COMMIT;
    
    트랜잭션 B
    BEGIN;
    UPDATE t SET val=0 WHERE a=9;  # レコード9をロック
    UPDATE t SET val=0 WHERE a=1;  # レコード1をロック
    COMMIT;
    
    이런 느낌
    터미널 A
    % while mysql test -e 'begin; update t set val=1 where a=1; update t set val=1 where a=9; commit;'; do echo -n .; done
    .........................................................................................................
    
    터미널 B
    % while mysql test -e 'begin; update t set val=1 where a=9; update t set val=1 where a=1; commit;'; do echo -n .; done
    .................................................ERROR 1213 (40001) at line 1: Deadlock found when trying to get lock; try restarting transaction
    
    BEGIN에서 거래를 쓰지 않고 UPDAATE 문장 하나만으로도 여러 개의 기록을 잠그면 사라질 수 있다.
    CREATE TABLE x (a INT, b INT, val INT, INDEX(a), INDEX(b));
    INSERT INTO x VALUES (1,9,0),(2,8,0),(3,7,0),(4,6,0),(5,5,0),(6,4,0),(7,3,0),(8,2,0),(9,1,0);
    
    트랜잭션 A
    UPDATE x SET val=0 WHERE a IN (1,9);
    
    트랜잭션 B
    UPDATE x SET val=0 WHERE b IN (1,9);
    
    터미널 A
    % while mysql test -e 'update x set val=0 where a in (1,9)'; do echo -n .; done
    .........................................................................................................
    
    터미널 B
    % while mysql test -e 'update x set val=0 where b in (1,9)'; do echo -n .; done
    .....ERROR 1213 (40001) at line 1: Deadlock found when trying to get lock; try restarting transaction
    
    이 경우 기록을 잠그는 순서는 조회에 사용된 인덱스의 순서이다
  • A 잠금(a,b)=(1,9)의 기록→성공
  • B 잠금(a,b)=(9,1)의 기록→성공
  • A는 (a,b)=(9,1)의 기록을 잠금→2의 잠금을 기다리는 방출
  • B는 (a, b)=(1,9)의 기록에 대해 잠금→대기 1의 잠금 방출
  • 그..그리고 자물쇠가 사라졌어요.
    또한 색인 b가 상반된 순서라면 같은 데이터 & 같은 조회라도
    CREATE TABLE x (a INT, b INT, val INT, INDEX(a), INDEX(b DESC));
    INSERT INTO x VALUES (1,9,0),(2,8,0),(3,7,0),(4,6,0),(5,5,0),(6,4,0),(7,3,0),(8,2,0),(9,1,0);
    
  • A 잠금(a,b)=(1,9)의 기록→성공
  • B는 (a, b)=(1,9)의 기록에 대해 잠금→대기 1의 잠금 방출
  • A 잠금(a,b)=(9,1)의 기록→성공
  • A 종료(=COMMIT), 1 잠금 해제
  • B 잠금(a,b)=(9,1)의 기록→성공
  • 이런 느낌으로 변하면 자물쇠가 생기지 않는다.
    그러나 DESC가 색인에 효과가 있는 것은 MySQL8.0에서 시작되기 때문에 5.7은 의미가 없다.

    좋은 웹페이지 즐겨찾기