사실 MySQL은 8.0 부터는 서버의 모든 시스템 테이블이 InooDB로 스토리지 엔진으로 교체됐고, 5.5까지는 전문 검색 및 공간 좌표 검색이 MyISAM 테이블 에서만 가능했지만, 이마저도 InnoDB가 지원되도록 바뀌었다. 즉 사실상 MyISAM 스토리지 엔진의 기능은 사실상 도태되는 상황이다.
그럼 세기의 대결이 아니지 않나 ? 맞다 사실 이번 글에서는 두 스토리지 엔진에 대한 비교를 조금 해보려 한다.
미안하다...이거 보여주려고 어그로 끌었다..
InnoDB와 MyISAM은 추구하는 목적부터가 다르다고 볼 수 있다.
InnoDB : 성능 적인 측면
MyISAM : 속도 적인 측면
그렇다면, 이 둘은 어떻게 서로가 추구하는 목적을 달성하기위해 구성되어 있을까
우선 InnoDB와 MyISAM의 차이는 어떻게 될까? 아래의 표를 보자
우선 MySQL version 5.5 기준으로 이전까지는 MyISAM이 기본 스토리지 엔진이었지만, 이후버전 부터는 InnoDB가 기본 스토리지 엔진으로 선택되었다.
MySQL Document에 InnoDB 스토리지 엔진에 대한 소개를 보면 기본적으로
InnoDB는 사용자의 데이터를 보호하기 위해 커및, 롤백 및 충돌 복구 기능을 갖춘 트랜잭션을 통해 ACID 모델을 따르고 있다. 그에 반해 MyISAM의 경우 ACID를 만족하지 않고있는걸 위 표를 보면 알 수 있다.
사실 데이터페이스 이론이 등장한 1970년 부터 ACID를 만족하는 데이터베이스가 유행하기 시작했으며, MySQL은 초기에 MyISAM을 기본 엔진으로 사용했지만, InnoDB스토리지 엔진을 도입하고 인수(2005년 핀란드 기반 회사인 Innobase를 Oracle이 인수함)하면서 부터 ACID를 만족하는 InnoDB로 변경되었다.
ACID는 트랜잭션 관리자가 모든 트랜잭션에 대해 보장하는 네가지 기본 속성을 학습하고 기억하기 위한 약어이자, 장치이다.
총 네 가지의 속성으로 구성되어 있으며, 원자성, 일관성, 격리, 내구성으로 이루어져 있다.
- 원자성(A)
두 개 이상의 개별 정보가 포함된 트랜잭션에서 모든 조각이 커밋되거나 전혀 커밋되지 않습니다.
- 일관성(C)
트랜잭션은 새롭고 유효한 데이터 상태를 생성하거나, 오류가 발생하면 모든 데이터를 트랜잭션이 시작되기 전의 상태로 되돌립니다.
- 격리(I)
진행 중이지만 아직 커밋되지 않은 트랜잭션은 다른 트랜잭션과 격리된 상태로 유지되어야 합니다.
- 내구성(D)
커밋된 데이터는 시스템에 저장되므로 오류가 발생하고 시스템이 다시 시작되는 경우에도 데이터를 올바른 상태로 사용할 수 있습니다.
기본적으로 ACID는 트랜잭션이 포함된다. 그러나, MyISAM의 경우에는 Transactional을 지원하지 않기 때문에 ACID를 만족시킬 수 없고, 해당부분이 MySQL의 기본 스토리지 엔진이 InnoDB로 교체되는 이유중의 하나 일 수 있다.
일반적으로 트랜잭션이란 데이터베이스에서 수행되는 일련의 여러 작업이며, 모두 단일 논리적 작업단위로 사용됩니다.(전체적으로 발생하거나 전혀 발생하지 않습니다.) 즉, 작업의 절반만 수행하고 결과를 저장하는 경우는 절대 없으며, 데이터베이스 트랜잭션이 실행중인 경우 데이터베이스 상태가 일시적으로 일관성이 없을 수 있지만, 커밋 및 종료시점에 변경사항이 적용됩니다.
물론 트랜잭션 실행중의 데이터 일관성을 위해 InnoDB는 MVCC를 사용하여 트랜잭션이 독립적으로 실행되는 것처럼 보이게하면서도 데이터 일관성을 유지할 수 있습니다.
반면 MyISAM의 경우 Transactional을 사용하지 않습니다. 이로 인한 문제점은 아래와 같습니다.
일관성 문제 : 만일 여러 개의 쿼리가 동시에 실행될 경우 데이터 일관성 문제가 생길 수 있습니다. 이를 위해 MyISAM의 경우 Table 단위를 Lock을 사용하는데 Table Lock을 사용했을때는 아래의 문제점이 발생할 수 있습니다.
동시성 문제 : MyISAM의 경우 테이블 락을 사용하여 일관성을 유지할 수 있지만, 테이블 락의 경우 특정 테이블에 대한 쓰기 작업이 이루어지는 동안 해당 테이블은 쓰기 및 일부 읽기작업으로 부터 보호되어 쓰기작업이 많이 발생하는 경우 다른 쓰기 작업 및 읽기 작업을 블로킹 하여 전체적인 처리 속도를 느리게 만들 수 있습니다.
InnoDB의 경우 RowLevel(행 단위)의 락을 사용하며, 이와 반대로 MyISAM의 경우 TableLevel(테이블 단위)의 락을 사용합니다. 이 둘의 차이점은 극명합니다.
RowLevel
행에 대한 Lock의 경우 가능한 가장 세분화된 수준의 잠금을 제공하므로, 트랜잭션에 대한 가능한 최상의 데이터 동시성 및 성능을 제공합니다.
또한, 락이 걸린 행만 다른 사용자에 의해 참조되는 경우, 다른 사용자는 대기 상태로 기다립니다.
TableLevel
테이블에 대한 락의 경우 데이터베이스의 전체 테이블을 보호하며, 한 사용자가 테이블의 구조를 변경하거나 전체 테이블을 수정하려고 할 때 사용됩니다. 만일 락이 걸린 테이블은 다른 사용자의 쓰기 또는 읽기작업 모두에 영향을 미칩니다.
동시성적인 측면에서 봤을때 행 단위의 Lock이 동시성이 높으며 성능이 우수하다고 볼 수 있다. 물론 이러한 데이터베이스의 락사용에 대한 결정은 상황에 맞춰 선택해야 하지만, 보편적으로 성능적인 측면을 고려했을땐 InnoDB가 더 우수하다고 볼 수 있다.
InnoDB 와 MyISAM의 경우 저장되는 기준이 다르다. 간단하게 설명하자면, InnoDB의 경우 기본적으로 프라이머리 키를 기준으로 클러스터링되어 저장되며, 이는 프라이머리 키 값을 순서대로 디스크에 저장된다는 뜻이다.
이를 통해 프리이머리 키가 클러스터링 인덱스 이기 때문에 프라이머리 키를 활용한 레인지 스캔은 상당히 빨리 처리 될 수 있다.
반면, MyISAM의 경우 프라이머리키를 기준으로 클러스터링 되어 저장되는 것이아닌 Insert의 순서대로 무작위로 데이터가 저장되며, 이는 삽입시에 무작위로 위치가 결정 되기 때문에 성능적으로 삽입의 경우에는 InnoDB보단 좋을 수있다.
사실 MyISAM을 비관적으로 보고있는 글처럼 보일수 있겠지만 맞다.
MySQL 8.0 부터는 InnoDB가 전문처리등 MyISAM이 남아있던 흔적들까지도 지원하면서 점점 MyISAM은 설 자리가 없는것도 사실이고, 이후에는 사장될꺼라는 의견도 많이 나오고 있는 추세이다. MyISAM을 필히 공부할 필요는 없지만, 사실 이 글의 의도는 InnoDB가 어떻게 성능적인 측면의 향상을 위해 어떠한 기능들을 사용하는 지를 보여주기 위함이다. 이 글을 읽는 사람들도 그렇게 느꼈다면 글을 매우 잘썼다고 생각해도 좋을거 같다.