본문 바로가기

독서/데이터베이스

트랜잭션과 잠금

728x90

트랜잭션이란 작업의 완전성을 보장하는 것으로 하나의 트랜잭션에 일어나는 모든 변경은 완전히 성공하거나 완전히 실패하도록 만들어주는 기능이다. 이것은 하나의 작업에서 일부만 성공해 데이터가 변경이 일어난 경우를 막기 위함인데 만약 서로 다른 트랜잭션에 동일한 데이터에 접근할 경우에는 잠금이 필요하게 된다. 잠금이란 동시성을 제거하기 위한 기능으로 하나의 레코드 또는 테이블에서 다른 트랜잭션에 의해 작업 중인 데이터에 접근해 수정하려는 행위를 막기 위한 기능이다. 데이터는 일관성을 지켜 신뢰성을 얻어야 하기 때문에 이 두 개의 기능은 매우 중요하다고 할 수 있다.

MySQL에서의 트랜잭션

MySQL에서 테이블 엔진에 따라 트랜잭션은 다르게 일어나는데 MyISAM 경우 부분 업데이트를 통해서 실패한 레코드만 롤백(Rollback)하는 반면에 InnoDB의 경우에는 트랜잭션 전체를 롤백한다. 이것 외에도 트랜잭션을 사용할 때 주의해야 할 점으로 트랜잭션의 범위를 최소화해야 한다는 것이다. 대부분의 데이터베이스는 커넥션 수를 제한하기 때문에 트랜잭션이 길어지게 된다면 커넥션을 붙잡고 있는 시간도 길어지게 되고, 이로 인해 성능 저하가 발생하기 때문이다.

MySQL 엔진의 잠금

전역 잠금(Global lock) 가장 범위가 큰 잠금으로, 이  SELECT를 제외한 대부분의 DDL, DML 문장의 실행이 잠금이 풀릴때 까지 대기 상태로 둔다. 이 잠금의 영향은 MySQL 서버 전체이며, 작업 대상 테이블이나 데이터베이스가 다르더라도 동일하게 영향을 미친다. MyISAM, MEMORY 테이블에 일관된 백업을 위해 사용됐다.
백업 잠금(Backup lock) 전역 잠금의 문제와 트랜잭션을 지원하는 InnoDB가 대두되면서 조금 더 가벼운 백업 잠금이 도입됐다. 이 잠금의 경우 테이블 스키마나 사용자 인증 관련 정보는 변경할 수 없지만, 일반적인 테이블의 데이터 변경은 허용된다.
테이블 잠금(Table lock) 개별 테이블 단위로 설정되는 잠금으로 명시적으로 테이블 잠금은 전역 잠금만큼 영향이 크기 때문에 특별한 경우에는 사용하지 않는다. 하지만 MyISAM, MEMORY 테이블의 데이터 변경 쿼리가 실행되면 묵시적 테이블 잠금이 발생하고 쿼리가 종료되면 다시 해제된다. InnoDB의 경우 레코드 기반의 잠금을 지원하기 때문에 데이터 변경 쿼리로 인해 묵시적인 테이블 락이 설정되지는 않는다.
네임드 잠금(Named lock) 임의의 문자열에 대해 잠금을 설정하는 것으로 사용자가 지정한 문자열에 대해 잠금을 수행한다. 이 잠금은 많은 레코드에 대해서 복잡한 요건으로 레코드를 변경하는 트랜잭션에 유용하게 사용될 수 있다. 예를 들어 한꺼번에 많은 레코드를 변경하는 쿼리의 경우 데드락의 원인이 되는데 이 경우 여러 프로그램들을 데이터의 유형에 맞게 분산해서 처리하면 간단히 해결된다.
메타데이터 잠금(Metadata lock) 데이터베이스 객체의 이름이나 구조를 변경하는 경우 자동으로 획득하는 잠금.

InnoDB 스토리지 엔진 잠금

InnoDB는 스토리지 엔진 내부에서 레코드 기반의 잠금 방식을 탑재하고 있어 MyISAM보다 훨씬 뛰어난 동시성 처리를 제공할 수 있다.

레코드 잠금(Record lock) 다른 상용 DBMS의 레코드 잠금과 동일한 역할을 함. 차이점은 InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다는 점이다. 인덱스가 없는 테이블의 경우 자동 생성된 클러스터 인덱스를 이용해 잠금을 설정한다.
갭 잠금(Gap lock) 레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하기 위한 잠금.
넥스트 키 잠금(Next key lock) 레코드 잠금과 갭 락을 합쳐 놓은 형태의 잠금. 이 잠그은 바이너리 로그에 기록되는 쿼리가 레플리카 서버에서 실행될 때 소스 서버에서 만들어 낸 결과와 동일한 결과를 만들어내도록 보장하는 것이 목적이다.
자동 증가 잠금 AUTO_INCREMENT 속성의 칼럼의 일련번호 값을 위해 InnoDB 스토리지 엔진에서는 자동 증가 잠금을 사용하는 테이블 수준의 잠금이 사용된다. 이 잠금은 새로운 레코드를 저장하는 쿼리에서만 필요하며 UPDATE, DELETE 등의 쿼리에서는 걸리지 않는다.

이처럼 트랜잭션은 개발자에게 필수적인 기능이지만 이로 인해 원활한 서비스를 방해할 수도 있다는 걸 기억하자.

'독서 > 데이터베이스' 카테고리의 다른 글

함수적 종속성  (0) 2022.01.09
SQL 메모 정리 [작성중]  (0) 2022.01.05
쿼리 작성 및 최적화  (0) 2021.12.30
실행 계획 분석  (0) 2021.12.29
프로그래머스 SQL JOIN  (0) 2021.12.29