DB 데드락

유수민·2022년 7월 10일
0

지식창고

목록 보기
18/64
post-thumbnail

📌DB Deadlock

일반적으로 DeadLock(교착상태)을 설명하자면, 둘 이상의 프로세스가 다른 프로세스가 점유하고 있는 자원을 서로 기다릴 때 무한 대기에 빠지는 상황을 말한다. DB에서의 데드락은 두 트랜잭션이 각각 Lock을 정하고 다음 서로의 Lock에 접근하여 값을 얻어오려고 할 때 이미 각각의 트랜잭션에 의해 Lock이 설정되어 있기 때문에 양쪽 트랜잭션 모두 영원히 처리가 되지않게 되는 상태를 말한다.
즉, DB Deadlock은 상대방이 소유하고 있는 Lock을 요청해서 작업의 처리를 진행하지 못하는 상태다.

📌왜 DB에서는 데드락을 일으킬지도 모르는 Lock을 사용할까?

DataBase는 데이터를 영속적으로 저장하고 있는 시스템이다. 이런 시스템은 같은 자원(데이터)에 대해서 동시에 접근하는 경우가 생길 수 밖에 없고, 이럴 경우 데이터가 오염 될 수 있는데 그렇게 되지 않도록 데이터의 일관성과 무결성을 유지해야할 필요가 있다.

예를 들어 수강신청 시스템에서 1명만이 정원으로 남게되었는데, 2사람이 거의 동시에 버튼을 누른 경우, 성공은 1명만 되야한다. 즉, 동시성 제어으로 인해 트랜잭션 명령들 간의 끼어들기가 가능한 상황에서 서로 간섭 없이 독립적으로 수행되어 하기 때문에, DBMS(DataBase Management System)가 사용하는 공통적인 방법이 Lock인 것이다.

잠금(Locking)은 트랜잭션의 실행 순서를 강제로 제어하여 직렬 가능한 스케줄이 되도록 보장한다. 하지만 lock과 unlock을 잘못 사용하면 데드락 상태에 빠질 수 있는 것이다.

📌Lock의 종류

📖1. Row-level Lock

  • 📚Shared Lock

    • Read Lock라고도 하는 공유락은 데이터를 읽을 때 사용하는 Lock이다.
    • select 문 같이 클라이언트가 읽기 작업하는 데이터 영역에 걸린다.
    • Read Lock은 같은 Read Lock 끼리는 동시에 접근이 가능하다. 즉, Database의 주요 기능인 데이터 일관성과 무결성을 해치지 않기 때문에 하나의 데이터를 읽는 것은 여러 사용자가 동시에 할 수 있다. 사용자가 데이터를 읽어 갈 뿐, 데이터 변경이 없기 때문에 가능하다.
    • 하나의 데이터 항목에 대해서 동시에 두 개 이상의 S-lock 설정이 가능하다.
    • Exclusive Lock의 접근을 막는다.
  • 📚Exclusive Lock

    • Write Lock이라고도 하는 베타락은 데이터를 변경할 때 사용하는 Lock이다.
    • 기본적으로 insert, update, delete 문 등 클라이언트가 쓰기 작업을 하는 데이터 영역에 걸린다. 읽기, 쓰기 연산 모두 가능하다.
    • 트랜잭션이 완료될 때까지 즉, Exclusive Lock이 끝나기 전까지 어떠한 접근도 허용하지 않는다. 이 Lock은 다른 트랜잭션이 수행되고 있는 데이터에 대해서 접근하여 Lock을 걸 수 없다.
    • 하나의 데이터 항목에 대해서는 하나의 X-lock만 가능하다.
      → lock이 해제될 때까지 대기하는 거라 Deadlock 발생 가능성 높음

📖2. Table-level lock

  • 📚Intention lock
    • SQL-server에서 데이터베이스나 테이블 내의 일부 데이터 영역에 이미 Shared Lock이나 Exclusive Lock이 걸려 있다는 것을 다른 커넥션에게 알리기 위해서 사용한다.
    • intention share lock과 intention exclusive lock
    • Table-level lock
      • select ... lock in share mode 실행시
        intention shared lock 이 테이블에 걸린 후 → 해당 row에 shared lock이 걸린다.
      • select ... for update, insert, delete 실행시
        intention exclusive lock이 테이블에 걸린 후 → 해당 row에 exclusive lock이 걸린다.
    → Intention lock을 사용해 Table-level lock을 걸더라도 테이블 두개를 한번에 잠그지 않는 이상 Deadlock은 발생할 가능성 높음

💡 Table-level → row-level으로 2단계로 lock 적용이유
이미 lock이 걸려있는 테이블에 다른 트랜잭션이 특정 row에 lock 거는 것 방지.row - level 상에서 lock이 걸린 상태(update,delete,,)일때 테이블 변경 방지.

💡update 할때!
보통은 update되는 대상 row에  Lock이 걸리지만, where절에 인덱스를 적절히 태우지 않거나 인덱스가 없는 경우는 테이블 전체에 Lock이 걸린다.
update를 하기 위해서는 우선적 Shared Lock를 거치고 Exclusive Lock로 흘러간다.
→ 같은 행에 A트랜젝션은 sharedLock을 가지고 싶어하고 B트랜잭션은 Shared Lock에서 Exclusive Lock로 가야할 때 데드락 발생 가능성 있음

📖3. Record Lock

  • row가 아니라 DB의 index record에 걸리는 lock
  • primary key 또는 unique index (multi-column unique index 포함)로 조회해서 하나의 인덱스 레코드에만 lock을 거는 것을 의미
  • row-level lock과 마찬가지로Shared Lock과 Exclusive Lock이 있다.
  • 이미 존재하는 row가 변경되지 않도록 보호하는 역활

📖4. gap Lock

  • 실제 존재하는 인덱스 레코드에 락을 거는것이 아니고 범위를 지정하기 위해 인덱스 레코드 사이의 범위(gap)에 락을 거는 것
  • Gap lock은 DB index record의 gap에 걸리는 lock이다. 여기서 gap이란 index 중 DB에 실제 record가 없는 부분 이다.
  • 해당 gap에 접근하려는 다른 쿼리의 접근을 막는다.
  • 조건에 해당하는 새로운 row가 추가되는 것을 방지하기 위한 역활

cf) 외래키에 의한 데드락

외래키는 부모테이블이나 자식 테이블에 데이터가 있는지 체크하는 작업이 필요하므로 잠금이 여러 테이블로 전파되고, 그로인해 데드락이 발생할 수 있다. 외래키 체크가 필요한 insert/update/delete에 대해서 Shared Lock을 설정

📖데드락이 발생 줄이기

  • 인덱스 설정 → 인덱스가 없으면 Lock이 걸리는 범위가 훨씬 넓어지기 때문에 교착상태가 발생하기 쉬워진다. ex) update

  • Isolation Level 조정
    - 1) READ UNCOMMITED : Share-lock 사용안함.
    - 2) READ COMMITED : 매번의 read 마다 Consistent read를 통한 새로운 snap shot을 생성하며, Share-lock을 사용안함
    - 3) REPEATABLE READ : Shared Lock도 트랜잭션 종료시까지 지속된다. UPDATE, DELETE 상태일때 unique index에 대해 찾으면 → index record에만 lock (record lock)
    range-type (범위로) 찾으면 → gap lock 사용
    - 4) SERIALIZABLE : Shared Lock이 트랜잭션 종료시까지 지속된다.

  • Lock Timeout 설정 ( 트랜잭션 처리속도를 최소화 )

  • 프로시저 우선순위 설정. 트랜잭션 진행방향을 같은방향으로 처리

  • 데드락 발생시 DBMS는 둘 중 한 트랜잭션에 에러를 발생시킴으로써 문제를 해결.

profile
배우는 것이 즐겁다!

0개의 댓글