본문 바로가기
DB/MySQL

[mysql/DB] 트랜잭션, 잠금 ,동시성

by windy7271 2024. 6. 21.
728x90
반응형

 

 

잠금 : 동시성을 제어하기 위한 기능

  • 여러 커넥션에서 동시에 동리한 자원을 요청할 경우 순서대로 한 시점에는 하나의 커넥션만 변경할 수 있게 해주는 역할

트랜잭션: 데이터의 정합성을 보장하기 위한 기능

  • MyISAM : 트랜잭션 지원X
  • InnoDB : 트랜잭션 지원

트랜잭션의 범위를 최소화 하는 것이 좋다. 범위가 넓으면 DBMS 서버가 높은 부하 상태로 빠지거나 위험한 상태로 빠지는 경우가 번번히 발생한다.

MySQL 에서의 잠금레벨

스토리지 엔젠 레벨 : 모든 스토리지 엔진에 영향x

MySQL 엔진 레벨 : 모든 스토리지 엔진에 영향o

 

락 을 사용하는 이유는  데이터베이스는 여러 사용자들이 같은 데이터를 동시에 접근하는 상황에서, 데이터의 무결성과 일관성을 지키기 위해 락을 사용한다.

과거에 레디스를 사용한 동시성 문제 해결의 대해 작성한 내용이 있는데 참고해주면 도움이 될 것 같다.

https://windy7271.tistory.com/entry/Redis-%EB%B6%80%EC%88%B4%EB%B2%84%EB%A6%AC%EA%B8%B05-%EB%A0%88%EB%94%94%EC%8A%A4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EB%B6%84%EC%82%B0-%EB%9D%BD

 

Redis 부숴버리기(5) 레디스를 사용한 동시성 문제 해결 - 분산 락

트랜잭션이 동시에 실행됐을 때 발생할 수 있는 문제 관련한 상황을 DB동시성 문제 라고 한다.1. Dirty Read한 트랜잭션이 다른 트랜잭션이 수정 중인 데이터를 읽을 수 있는 문제아직 commit되지 않

windy7271.tistory.com

 

  • 테이블 락: 테이블 데이터 동기화를 위한 락
  • 글로벌 락 : 잠금 가운데 가장 범위가 큰 락
    • 모든 변경 작업을 멈춘다.
    • 한 세션에서 글로벌 락을 획득하면 다른 세션에서 Select 을 제외하고 DDL, DML 을 실행하는 경우 글로벌 락이 해제될 때까지 대기상태로 남는다.
  • 백업 락 : mysql 8.0 부터 InnoDB가 기본 엔진으로 채택되어 Xtrabackup, Enterprise Backup 과 같은 백업 툴들의 안정성 실행을 위해 백업 락이 도입 된다.
    • 일반적인 데이터 변경은 허용 된다. 주로 백업은 레플리가 서버에서 실행된다.
    • 정상적으로 복제는 실행되지만 백업의 실패를 막기 위해 DDL 명령이 실행되면 복제를 중지하는 역할은 한다.
  • 테이블 락 : 개별 테이블 단위로설정되고, 명시적 묵시적으로 특정 테이블의 락을 획득 할 수 있다.
    • 테이블을 잠그는 작업은 글로벌 락과 동일하게 온라인 작업에 상당한 영향을 미친다.
    • 묵시적인 테이블 락은 테이블의 데이터를 변경하는 쿼리를 실행하면 발생한다. 서버의 데이터가 변경되는 테이블에 잠금을 설정하고, 데이터를 변경하고 즉시 잠금을 해제한다. 자동적으로 된다. 하지만 InnoDB 테이블의 경우, 레코드 기반의 잠금을 제공해 데이터 변경 쿼리로 인해 묵시적인 테이블 락이 설정되지는 않는다. → DML 을 무시되고 , DDL 의 경우에만 영향을 미친다.
  • 메타데이터 락 : 데이터베이스 객체 의 이름이나 구조를 변경하는 경우에 획득하는 잠금이다. 명령어를 통해 획득하거나 해제하는 것이 아닌. 테이블의 이름이 변경되는 경우 자동으로 획득하는 잠금이다.
    • 메타데이터 락 + 트랜잭션 
      • 예를들어 insert만 실행되는 로그 테이블이 있을때 테이블의 구조가 변경이 필요하다. -> 
        Online DDL 을 이용해서 변경할 수 있지만, 시간이 오래 걸리는 경우 
        언두 로그의 증가와 Online DDL  이 실행되는 동안 누적된 Online DDL  버퍼의 크기등 고민 할게 많다.
        해결방법 : 새로운 구조의 테이블 생성 -> 최근 데이터까지 pk 인 id값을 범위별로 나눠 스레드로 복사한다. 
    • Online DDL은 테이블의 구조를 변경(스키마 변경)을 실행하는 도중에도, INSERT나 UPDATE와 같은 DML들을 실행할 수 있도록 해주는 기능이다.
  • 네임드 락 : 사용자의 필요에 맞게 사용
    • 데이터베이스 객체가 아닌 사용자가 지정한 문자열에 대해 락을 획득하고 반납하는 잠금으로, Lock에 이름을 지정하여 어플리케이션 단에서 제어가 가능하다.
    • 한 꺼번에 많은 레코드를 변경하는 쿼리를 사용하면 데드락의 원인이 된다. 이러한 경우 프로그램끼리 분류해서 네임드 락을 걸어 실행하면 간단하게 해결될 수 있다.
    • 중첩가능, 한 번에 해지 가능
    • getLock 함수를 사용해 락을 얻고, releaseLock()으로 해지한다.

 


InnoDB 엔진 잠금

레코드 기반의 잠금 방식 이기 때문에 뛰어난 동시성 처리가 가능하다.

 

  • 갭 락 : 레코드 와 레코드 사이의 간격을 잠그는 락, 레코드 락 처럼 특정 데이터에 대한 잠금 용도로 사용하는 것이 아니라, 데이터의 생성, 수정, 삭제를 방지하는데 사용되는 잠금 방식이다
  • 레코드 락 : 인덱스의 레코드를 잠군다. 인덱스가 없는 테이블이더라고 내부적으로 자동 생성된 클러스터 인덱스를 이용해 잠금을 설정한다.
    • 변경해야 할 레코드를 찾기 위해 검색한 레코드를 모두 락을 걸어야 한다.
    • 단점 : 각 클라이언트 간의 동시성이 상당히 떨어져서 한 세션에서 UPDATE 작업을 하는 중 다른 클라이언트는 그 테이블을 업데이트 하지 못하고 기다려야 하는 상황이 발생한다.
  • 넥스트 키락 : 레코드 락 + 갭 락 RepeaTable Read 격리 수준 을 사용한다
  • 넥스트 키락, 갭락
    • 바이너리 로그에 기록되는 쿼리가 레플리카 서버에서 실행 될때 소스 서버에서 만들어 낸 결과와 동일한 결과를 만들어내도록 보장하는 것이 주 목적이다.
    • 데드락, 다른 트랜잭션을 기다리게 하는 일이 드물다.
    • 해결법 : 바이너리 로그 포맷을 ROW 형태로 바꿔 락을 줄인다.

레코드 락, 넥스트 키 락 , 갭 락

 

MySQL 격리 수준

 

https://windy7271.tistory.com/entry/Redis-%EB%B6%80%EC%88%B4%EB%B2%84%EB%A6%AC%EA%B8%B05-%EB%A0%88%EB%94%94%EC%8A%A4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EB%B6%84%EC%82%B0-%EB%9D%BD

 

Redis 부숴버리기(5) 레디스를 사용한 동시성 문제 해결 - 분산 락

트랜잭션이 동시에 실행됐을 때 발생할 수 있는 문제 관련한 상황을 DB동시성 문제 라고 한다.1. Dirty Read한 트랜잭션이 다른 트랜잭션이 수정 중인 데이터를 읽을 수 있는 문제아직 commit되지 않

windy7271.tistory.com

 

과거에 레디스를 정리하면서 격리수준을 정리해놨다.

 

MySQL을 사용한다면 최소한 Read Commited 이상의 격리 수준을 사용하는 것이 좋다. (기본으로 사용되는 격리 수준)

 

무조건 Serializable 을 설정하면 좋지 않나 라는 생각이 들었는데

일반적인 DBMS에서 일어나는 문제는 Phantom Read 이다. 하지만 InnoDB 스토리지 엔진에서는 갭 락과 넥스트 키 락 덕분에 

Repeatable Read격리 수준에서도 Phantom Read이 발생하지 않기 때문에 굳이 Serializable 는 사용할 필요는 없다.

 

 

 

반응형

댓글