MySQL Table Lock에 관한 이해

Overview

Table Lock 스토리지 엔진 사용 시 반드시 알아야할 사항을 정리 드리겠습니다.

근래에는 물론 InnoDB가 아~주 많이 사용되고 있겠지만, 여전히 서비스에서는 MyISAM이 쓰이고 있습니다. MyISAM은 MySQL의 대표적인 스토리지 엔진이면서 내부적으로는 Table Lock으로 동작합니다.

관련 스토리지 엔진에 관한 설명은 MySQL특성을 정리한 반드시 알아야할 MySQL 특징 세 가지 포스팅을  참고하시면, 간단한 비교를 하실 수 있습니다. 자 그럼 Table Lock 스토리지 엔진 사용 시 반드시 알아야할 사항을 정리 드리겠습니다.

Table Lock 이해

MySQL에서 Table Lock은 다음 기준에 의해서 부여됩니다.

Write Lock
아무런 Lock이 없으면, 해당 테이블에 Write Lock을 걸어서 데이터 읽기 또는 변경 작업을 수행하지 못하게 합니다. 만약 Read 혹은 Write Lock이 존재하면 Write Lock 큐에 Lock을 넣어서 해당 Lock이 풀릴 때까지 대기합니다.

Read Lock
아무런 Write Lock이 없으면, Read Lock을 걸어서, 데이터 변경 작업을 수행하지 못하도록 합니다. 만약 Write Lock이 있으면 Read Lock 큐에 Lock을 넣고 데이터 변경 작업이 종료될 때까지 대기합니다.

기본적으로 Write Lock이 Read Lock보다 우선 순위가 높지만,
다음과 같이 LOW_PRIORITY 로 변경 가능합니다.
Example)
mysql> INSERT INTO LOW_PRIORITY table_name…
mysql> DELETE LOW_PRIORITY FROM table_name…
mysql> UPDATE LOW_PRIORITY table_name SET…

참고) Internal Locking Methods

위를 다시 간단하게 정리하자면, Write Lock 상태에서는 다른 세션이 해당 테이블 접근이 불가한 상태이고, Read Lock 상태는 다른 세션이 데이터를 Read까지만 가능하다고 볼 수 있습니다.

그러나! 만약에 Write 또는 Read 수행이 오래 걸리는 경우는 어떨까요? Read Lock은 다른 Read 세션에 영향을 미치지 않을 것으로 보이지만, 때로는 Dead Lock을 유발하는 요소가 될 수도 있습니다.

Example

다음과 같은 경우를 예를 들어보겠습니다. 테이블은 MyISAM 엔진입니다.

Session 1

## 수행 시간이 오래 걸리는 조회 쿼리 발생
mysql> SELECT * FROM tab01 WHERE  sleep(1000);

이 경우 다른 세션에서도 tab01 테이블에서 얼마든지 데이터 조회가 가능합니다.

Session 2

## Read Lock 상태 테이블에 데이터 변경
mysql> UPDATE tab01 SET c1 = '' WHERE i = 4;

Update 쿼리는 Session1의 Select 쿼리가 종료될 때까지 대기합니다.

Session 3

## Read Lock 상태이고, Write Lock이 대기 상태에서 Select 수행
mysql> SELECT * FROM tab01 LIMIT 10;

Session 2 의 Write Lock에 의해 Read 불가한 상태로 빠집니다.

프로세스 현황을 확인해보면 아래와 같습니다.
Table Lock Process List

정상적이라면 Select 수행되는 동안 다른 세션에서도 Select가 수행되어야 하는데, 쿼리 우선 순위에 의해서 Select 세션이 Lock 상태로 빠진 것을 확인할 수 있습니다.

Conclusion

MySQL Replication 사용 시 Slave 서버에서 Dead Lock은 위와 같은 상황에서 얼마든지 발생할 수 있기 때문에, 반드시 알고 있어야 합니다. (통계성 SQL이 실행되는 테이블에 Update 발생 시 다른 세션에서는 해당 테이블 데이터 조회 불가)

MyISAM 스토리지 엔진이 트랜잭션이 많은 경우 부적합한 가장 큰 이유입니다.^^

MySQL Replication 이해(1) – 개념

Overview

오늘은 조금더 제너럴한 주제를 가지고 정리를 할까합니다.
바로 MySQL Replication 입니다. MySQL Community에서 유일하게 HA 또는 분산 구성을 할 수 있는 유일한 기능입니다. 물론 “MySQL+DRBD 구성”와 같이 HA를 구성하는 방법도 있습니다만, MySQL 제품이 아니므로 스킵~!

먼저 Replication에 대해 간략하게 말씀 드리겠습니다.

MySQL Replication이란?

MySQL Replication이란 말 그대로 복제입니다. 영어 사전에 나온 듯한 DNA는 아니지만 데이터를 “물리적으로 다른 서버의 저장 공간” 안에 동일한 데이터를 복사하는 기술이죠.

다음 그림은 MySQL Replication을 가장 간단하게 나타낸 그림입니다.  데이터 변경을 마스터 장비에서만 수행하기 때문에 마스터 장애 시에는 전체 노드에 데이터 쓰기 작업이 불가능한 한계가 있습니다.

MySQL Replicaton Master Slave
MySQL Replicaton Master Slave

아래 그림은 MySQL Replication과 Oracle RAC스토리지 구조를 가장 간단하게 묘사한 그림입니다.

MySQL Replication과 Oracle RAC 비교
MySQL Replication과 Oracle RAC 비교

MySQL복제라는 말과 같이, 디스크를 독립적으로 분리하여 데이터를 유지합니다.

이에 반해 오라클은 RAC 구성 시에는 공유 스토리지(SAN,iSCSI) 장비를 중간에 두고 DB를 이중화 합니다. 엄격하게 다시 말하자면, “MySQL Replication은 데이터를 이중화”하는 것이고, “Oracle RAC는 DB를 이중화하는 개념”입니다.

MySQL은 오직 단일 마스터에서만 데이터 변경 작업을 수행할 수 있고, Oracle은 하나의 스토리지를 중간에 두고 여러 노드에서 데이터 변경 작업이 일어날 수 있습니다.  그렇기 때문에 MySQL에서는 쓰기 부하 분산은 불가능하지만, 읽기 부하 분산은 가능합니다. 그리고 특정 노드 디스크 장애가 전체 데이터 유실로 이어지지 않습니다. 데이터는 “복제”되니까요. Oracle은 어느정도의 읽기/쓰기 부하 분산은 가능하지만 공유 스토리지를 쓰는 만큼 스토리지 장애에는 상당히 취약합니다. 어디까지나, 일반 구성 시 비교를 한 것임을 알아주세요^^

마스터, 슬레이브 간 Data 복제 방법

MySQL Replication은 로그 기반으로 비동기적으로 데이터를 복제합니다. 마스터에서는 데이터 변경 작업이 수행되면 Binary Log라는 곳에 이력을 기록을 하는데, Statement, Row 그리고 Mixed 등 세 가지 방식이 있습니다.

Statement-based Type
MySQL 3.23 이후로 도입된 방식
실행된 SQL을 그대로 Binary Log에 기록
Binary Log 사이즈는 작으나, SQL 에 따라 결과가 달라질 수 있음
(Time Function, UUID, User Defined Function)
Row-based Type
MySQL 5.1부터 도입된 방식
변경된 행을 BASE64로 Encoding하여 Binary Log에 기록
특정 SQL이 변경하는 행 수가 많은 경우 Binary Log 사이즈가 비약적으로 커질 수 있음
Mixed Type (Statement + Row)
기본적으로 Statement-Based Type으로 기록되나, 경우에 따라 Row-base Type으로 Binary Log에 기록

그렇다면 복제는 어떤 방식으로 이뤄질까요? 아래 그림으로 설명 드리겠습니다.

MySQL에서 데이터 복제 방법
MySQL에서 데이터 복제 방법
  1. Master에서 데이터 변경이 일어나면 자신의 데이터베이스에 반영합니다.
  2. Master에서 변경된 이력을 Binary Log에 기록 후 관련 이벤트를 날립니다.
  3. Slave IO_THREAD에서 Master 이벤트를 감지하고,
    Master Binary Log 자신의 Relay Log라는 곳에 기록을 합니다.
  4. Slave SQL_THREAD는 Relay Log를 읽고 자신의 데이터베이스에 기록을 합니다. (4,5단계)

기억해야할 사항은 마스터에서는 여러 세션에서 데이터 변경 처리가 가능하지만, 슬레이브에서는 오직 하나 SQL Thread에서만 데이터 변경 처리가 가능한 점입니다. 그렇기 때문에 마스터에 데이터 변경 트래픽이 과도하게 몰리게 되면 마스터/슬레이브 간 데이터 동기화 시간이 크게 벌어질 수도 있습니다.

마치며..

리플리케이션을 잘 활용하면, 부하분산 뿐만 아니라 고가용성 그리고 버전 테스트 등 여러 분야에 멋지게 사용할 수 있습니다. 차근차근 이러한 내용을 정리해서 포스팅하도록 하겠습니다.
일단, 다음 번에는 실제 리플리케이션 구성 방법에 대해서 먼저 진행할께요^^
좋은 하루 되세요~!