하나의 논리적인 작업 셋을 의미하며 여러 개의 쿼리가 포함되어 해당 작업 셋 자체가 전부 적용되거나 전부 적용되지 않음 즉 데이터 정합성을 보장하는 기능이다.
MySQL에는 여러 스토리지 엔진이 있는데 InnoDB만 트랜잭션을 제공해준다.
따라서 Memory 또는 MyISANM 스토리지 엔진을 사용한다면 오류가 발생해도 오류가 나기전 쿼리는 반영된다. 심지어 한개의 insert 쿼리에서 오류가 나더라도 오류나기 이전 값들은 반영이 되는데 이를 부분 업데이트라고 부른다.
부분 업데이트와 같이 쿼리 중 일부만 반영되기를 원하는 사용자는 없을 것이다.
그럼에도 불구하고 InnoDB스토리지 엔진을 사용하지 않을 경우 실패할때마다 재처리 작업이라는 불편을 감수 해야된다.
따라서 트랜잭션을 제공해주는 InnoDB 스토리지 엔진을 무조건 사용해야해도 무방하다.
보통 애플리케이션 개발자는 로직을 작성할 때 한개의 요청에서 여러가지 작업을 하는 경우가 있다. 이럴 경우 로직 시작부터 트랜잭션을 시작한 다음 모든 비즈니스 로직이 끝나야 커넥션을 반납하는 경우가 많은데 이는 제한적인 커넥션(자원)을 필요없이 소모하기 때문에 DB 접근이 필요한 경우에 커넥션을 가져와 트랜잭션을 시작하고 DB관련 작업이 끝나면 즉시 커넥션을 반납하도록 해야된다.
한마디로 정리하면 트랜잭션이 필요한 최소 범위만을 적용해서 사용해야 한다.
데이터에 대한 충돌(경합)이 자주 발생한다고 가정하며, 문제가 발생하지 않도록 미리 락을 거는 방식입니다.
데이터 수정 전(혹은 읽기 시)에 바로 잠금을 설정하여, 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 차단합니다.
일반적으로 데이터베이스의 물리적 락(Physical Lock), 즉 레코드 락, 테이블 락, 글로벌 락 등이 비관적 락에 속합니다.
예: SELECT ... FOR UPDATE, LOCK IN SHARE MODE.
데이터 충돌이 별로 발생하지 않는다고 가정하며, 데이터에 접근할 때 잠금을 설정하지 않는 방식입니다.
데이터 변경 직전에 충돌 여부를 확인하고, 충돌이 있으면 트랜잭션을 롤백하는 방식으로 동시성을 관리합니다.
기본적으로 실제 데이터베이스 락을 사용하지 않으며, 버전 관리(versioning) 기법이나 타임스탬프를 이용하여 충돌을 감지합니다.
예: 업데이트 시 WHERE 절에 버전 필드를 추가하여 버전 충돌을 확인.
글로벌 락
FLUSH TABLES WITH READ LOCK 명령으로 획득 가능하며 잠금 중 가장 범위가 큰 잠금이다.
특정 세션에서 글로벌 락을 획득하면 다른 세션은 Select를 제외한 대부분의 쿼리에서 대기해야한다. 글로벌 락의 범위는 MySQL 서버 전체이다.
글로벌 락은 데이터 백업을 할때 사용되곤 하는데 MySQL8.0부터는 InnoDB 스토리지 엔진이 트랜잭션을 지원하기 때문에 일관성이 보장되어 모든 데이터 작업을 멈출 필요가 없어졌다.
그래서 해당 버전부터는 백업 락이라는 전용 락을 따로 만들어 사용된다.
테이블 락
개별 테이블 단위로 설정되는 잠금이다. 묵시적, 명시적 방법이 있으며 명시적 방법은 글로벌 락과 빕스하게 부하가 걸리며 자주 사용할 일이 없다.
묵시적 락은 MyISAM, MEMORY 스토리지를 쓰는 테이블에 변경 쿼리가 실행되면 테이블 락을 걸고 변경 후 즉시 락을 푸는 형태이다.
InnoDB도 사용은 가능하지만 별도의 레코드 기반의 잠금을 사용하기 때문에 DML에서는 묵시적으로 테이블 락이 걸리지는 않고 DDL의 경우에만 락이 걸린다.
네임드 락
문자열에 대해서 GET_LOCK() 함수를 이용해 네임드 락을 얻을 수 있다. 여기서 문자열은 단순히 사용자가 지정한 문자열을 말하며 컬럼의 값과 같은 데이터베이스에 객체와는 상관 없다.
메타데이터 락
데이터베이스 객체의 이름이나 구조를 변경하는 경우 획득하는 락이다. 명시적 획득은 불가능하고 테이블 정보를 변경하는 경우 자동으로 적용되는 락이다.
InnoDB 스토리지 엔진은 레코드 기반의 잠금 기능을 제공하고 있다.
레코드 락
레코드 자체만을 잠그는 락을 의미하며 실제로는 인덱스의 레코드를 잠근다는 특징을 가진다.
테이블에 인덱스가 없는 경우가 있는데 이러한 경우는 내부적으로 자동 생성된 클러스터 인덱스를 이용해 잠금을 사용한다.
갭 락
특정 레코드와 인접해 있는 레코드 사이의 간격을 잠그는 것을 의미하며 사이에 새로운 레코드가 생성되는 것을 제어하는 역할을 한다. 갭 락은 단독으로 사용되기 보다 다음에 설명할 넥스트 키 락의 일부로 사용된다.
넥스트 키 락
레코드 락과 갭 락을 합쳐놓은 형태로 과거 버전에서 많이 사용되던 락이다.
바이너리 로그에 기록되는 쿼리가 레플리카 서버에서 실행될 때 소스 서버에서 만들어 낸 결과와 동일한 결과를 만들어내도록 보장하는 용도의 락이다. 그런데 해당 락은 데드락이 발생하거나 다른 트랜잭션을 교착상태에 빠지게 해서 사용을 자제하는 것이 좋다.
자동 증가 락
테이블 컬럼에 자동 증가하는 숫자 값을 생성하기 위해 AUTO_INCREMENT라는 컬럼 속성을 제공하는데 해당 숫자 값은 테이블에서 유일한 값임을 보장해준다.
이를 보장해주기 위해서 자동 증가 락을 사용하는데 해당 락은 트랜잭션과 상관없이 insert, replace 쿼리와 같이 새로운 레코드를 적재할 때 걸렸다가 쿼리 완료 시 즉시 해제된다.
그래서 insert시 자동 증가 락이 걸리면 다른 사용자가 insert할 경우 대기해야 했었다.
하지만 5.1 버전부터는 innodb_autoinc_lock_mode 시스템 변수를 이용해서 대량 insert이면서 행의 수를 정확히 알 수 있을때는 락을 걸지 않고 래치(뮤텍스)를 이용해 해당 값을 생성하는데 이 값은 유일한 값이지만 연속적이지 않을 수 있다.