크게 MySql 엔진과 스토리지 엔진으로 구분할 수 있다
다음 작업들을 실행
글로벌 메모리
로컬 메모리
SHOW PLUGINS;
다음과 같은 플러그인의 단점을 보완하기 위해 등장
동일한 쿼리를 실행했을때 캐시된 결과를 반환해 성능 향상을 가져올 수 있지만, 테이블에 변경 사항이 있을때는 다른 결과를 반환하는 단점이 있었다
이에 MySql8.0에서는 삭제되었음
MySql 8.0 버전부터는 테이블의 구조 정보나 스토어드 프로그램의 코드 관련 정보를 모두 InnoDB 테이블에 저장
스키마 변경 작업 중간에 서버가 종료되더라도 스키마 변경이 완전 성공 혹은 완전 실패로 정리
레코드 기반의 잠금을 제공하여 높은 동시성 처리가 가능하고 안정적이며 성능이 뛰어나다
프라이머리 키 값의 순서대로 디스크에 저장
세컨더리 인덱스는 레코드의 주소 대신 프라이머리 키의 값을 논리적인 주소로 사용
프라이머리키를 이용한 레인지 스캔이 빠르기 때문에 프라이머리 키의 비중이 높게 설정 됨
외래키는 좋은 가이드의 역할을 할 수 도 있지만 때로는 데드락을 발생 시키는 문제를 야기할 수 있기에 주의해 사용해야 한다
외래키가 복잡하게 얽혀서 수정하기 어려울때는 다음 커맨드로 외래 키 관계에 대한 체크 작업을 일시적으로 멈출 수 있다
SET foreign_key_checks=OFF;
외래키 관계를 가진 부모 테이블의 레코드를 삭제했다면 반드시 자식 테이블의 레코드도 삭제해서 일관성을 맞춘 후 다시 외래키 체크 기능을 활성화 해야 한다
SET foreign_key_checks=ON;
잠금을 사용하지 않는 일관된 읽기를 제공하는데 목적이 있음
멀티 버전: 하나의 레코드에 대해 여러 개의 버전이 동시에 관리
시스템 변수에 설정된 격리 수준에 따라 작업 중인 레코드의 결과가 다르게 조회 됨
READ_UNCOMMITTED: InnoDB 버퍼 풀이 현재 가지고 있는 변경된 데이터를 읽어 반환
READ_COMITTED 이상의 격리 수준: 변경되기 이전의 내용을 보관하고 있는 언두 영역의 데이터를 반환
격리 수준이 SERIALIZABLE이 아닌 경우 읽기 작업은 다른 트랜잭션의 변경 작업과 관계 없이 잠금을 대기하지 않고 바로 실행
잠금이 교착상태에 빠지지 않았는지 체크하기 위해 잠금 대기 목록을 그래프 형태로 관리
InnoDB 스토리지 엔진이 교착상태에 빠진 트랜잭션들을 찾아서 그 중 하나를 강제 종료 시킴(이 때 기준은 언두 로그 양이 적은 것을 종료)
동시 처리 스레드가 매우 많아지면 데드락 감지 비용이 비싸지기 때문에 innodb_deadlock_detect를 OFF로 설정하는 것도 가능하다(이때 default 값은 50초인데 이보다 낮게 설정하는게 좋다)
InnoDB 데이터 파일은 MySql 서버가 시작될 때 항상 자동 복구를 수행
InnoDB의 복구를 위해 innodb_force_recovery 옵션에 설정 가능한 값은 1부터 6까지
스토리지 엔진에서 가장 핵심적인 부분으로 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시해 두는 공간
크기를 조절할 수 있기 때문에 버퍼 풀의 크기를 적절히 작은 값으로 설정해 상황을 봐 가면서 증가 시키는 것이 좋다
전체 메모리 공간이 8GB 미만이라면 50% 정도 InnoDB 버퍼 풀로 설정
그 이상이라면 50%에서 시작해 조금 씩 올려서 조정하면 된다
innodb_buffer_pool_size 시스템 변수로 크기를 설정하는 것이 가능하며 동적으로 크기를 확장하는 것이 가능하다
크리티컬한 변경이기에 가능하면 한가한 시점을 골라 진행하는 것이 좋다
버퍼풀을 여러개로 쪼개어 관리할 수 있게 개선하여 내부 잠금 경합 문제를 개선했다
버퍼 풀의 페이지 크기 조각을 관리하기 위해 InnoDB 스토리지 엔진은 크게 LRU 리스트, 플러시, 그리고 프리 리스트라는 3가지 자료 구조를 관리
LRU 리스트는 디스크로부터 한 번 읽어온 페이지를 최대한 오랫동안 버퍼풀 메모리에 유지해 디스크 읽기를 최소화 하는게 목적이다
InnoDB 스토리지 엔진에서 데이터를 찾는 과정
플러시 리스트는 디스크로 동기화되지 않은 데이터를 가진 데이터 페이지의 변경 시점 기준의 페이지 목록을 관리
InnoDB의 버퍼 풀은 서버의 메모리가 허용하는 만큼 크게 설정할 수 록 쿼리 성능이 빨라진다
InnoDB 스토리지 엔진에서 리두 로그는 1개 이상의 고정 크기 파일을 연결해서 순환 고리 처럼 사용
LSN: 리두 로그 파일은 기록될 때마다 로ㅗ그 포지션은 계속 증가됨 → 리두 로그 공간의 시작점이 된다
8.0으로 업데이트 되면서 더티 페이지를 디스크에 동기화하는 부분에서 예전과 같은 디스크 쓰기 폭증 현상은 발생하지 않는다
다음 두가지 플러시 기능을 백그라운드로 실행
워밍업: 디스크의 데이터가 버퍼 풀에 적재돼 있는 상태
워밍업이 잘되어 있으면 성능이 매우 뛰어나진다
버퍼풀을 덤프하여 버퍼 풀의 상태를 백업할 수 있고 서버를 다시 시작하면 버퍼 풀의 상태를 다시 복구할 수 있다
이렇게 자동으로 버퍼 풀의 상태를 자동으로 복구할 수 있게 설정하는 것이 좋다
information_schema 데이터베이스에 innodb_cached_indexes 테이블에서 인덱스별로 데이터 페이지가 얼마나 InnoDB 버퍼 풀에 적재돼 있는지 확인할 수 있다
데이터 안정성을 위해 사용하는데 HDD에서는 별 부담이 되지 않지만 SSD에서는 부담스럽다.
부담스럼더라도 데이터의 무결성을 위해서 활성화 하는 것이 좋다
트랜잭션과 격리 수준 보장을 위해 Insert, Update, Delete로 변경되기 이전 버전의 데이터를 백업한 것
트랜잭션 보장: 트랜잭션이 롤백되면 변경 이전 데이터로 복구해야 하는데, 이때 언두 로그에 백업해둔 이전 버전의 데이터를 이용해 복구
격리 수준 보장: 특정 커넥션에서 데이터를 변경하는 도중에 다른 커넥션에서 데이터를 조회하면 트랜잭션 격리 수준에 맞게 변경중인 레코드를 읽지 않고 언두 로그에 백업해둔 데이터를 읽어 반환
8.0으로 업데이트하면서 순차적으로 사용해 디스크 공간을 줄이는 것도 가능하며, 필요한 시점에 사용 공간을 자동으로 줄여 주기도 한다
트랜잭션이 장시간 유지되는 것은 성능상 좋지 않기 때문에 모니터링 하고 있는 것이 좋다
언두 테이블스페이스: 언두 로그가 저장되는 공간
하나의 언두 테이블스페이스는 1개 이상 128개 이하의 롤백 세그먼트를 가지며, 롤백 세그먼트는 1개 이상의 언두 슬롯을 가진다
최대 동시 트랜잭션 수 = InnoDB 페이지 크기 / 16 롤백 세그먼트 개수 언두 테이블 스페이스 개수
인덱스를 업데이트 하는 작업은 인덱스가 많다면 많은 자원을 소모
체인지 버퍼: 디스크로부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 임시 공간에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상 시키는 방법
리두 로그는 하드웨어나 소프트웨어 등 여러 가지 문제점으로 인해 서버가 비정상적으로 종료됐을 때 데이터 파일에 기록되지 못한 데이터를 잃지 않게 해주는 안전장치
MySql은 성능을 고려해 쓰기보다 읽기 성능을 고려한 자료 구조를 가지고 있고 성능저하를 막기 위해 데이터 변경 내용을 먼저 로그로 기록한다
리두 로그는 트랜잭션이 커밋되면 즉시 디스크로 기록되도록 해야 비정상적으로 종료됐을 때 직전까지의 트랜잭션 커밋 내용이 리두 로그에 기록될 수 있고 장애 직전 시점까지의 복구가 가능해진다
로그 버퍼의 크기는 16MB 수준에서 설정하는 것이 좋은데 TEXT 같이 큰 데이터를 자주 변경하면 크게 설정하는 것이 좋다
MySql의 리두 로그 아카이빙 기능은 데이터 변경이 많아서 리두 로그가 덮어쓰인다고 하더라도 백업이 실패하지 않게 해준다
아카이빙된 리두 로그가 저장될 디렉터리를 innodb_redo_log_archive_dirs 시스템 변수에 설정해야 한다
MySql 8.0 부터는 수동으로 리두 로그를 활성화하거나 비활성화할 수 있다
ALTER INSTANCE DISABLE INNODB REDO_LOG;
리두 로그가 비활성화된 상태에서 비정상적으로 종료되면 마지막 체크포인트 이후 시점의 데이터는 복구할 수 없고, 데이터의 일관성이 깨질 수 있기 때문에 끄지 않는 것이 좋다
어댑티브 해시 인덱스: 사용자가 수동으로 생성하는 인덱스가 아니라 InnoDB 스토리지 엔진에서 사용자가 자주 요청하는 데이터에 대해 자동으로 생성하는 인덱스
기존의 B-Tree 인덱스도 데이터의 처리가 빠르지만, 특정 값을 찾기 위해서는 리프노드를 찾아가야 하기 동시에 많은 작업을 처리하면 성능이 안좋아지는데, 이때 어댑티브 해시 인덱스는 검색 시간을 줄여줄 수 있다
어댑티브 해시 인덱스는 자주 읽히는 페이지의 키 값을 이용해 인덱스를 만들어 루트부터 리프 노드까지 찾아가는 비용이 없어진다
어댑티브 해시 인덱스가 성능 향상에 도움이 되지 않는 경우
어댑티브 해시 인덱스가 성능 향상에 도움이 되는 경우
어댑티브 해시 인덱스 또한 저장 공간인 메모리를 사용하고, 테이블의 삭제 작업에도 많은 영향을 미치는 등 불필요한 오버헤드를 발생 시킬 수 있다
MySql 8.0 부터는 모든 시스템 테이블이 InnoDB를 사용하게 교체
MyISAM, MEMORY 스토리지 엔진은 도태되는 중
InnoDb의 버퍼 풀과 비슷한 역할을 하지만 인덱스만을 대상으로 작동
키 캐시는 99%를 유지하는게 좋고 99% 미만이면 캐시를 조금 더 크게 설정하는 것이 좋다
MyISAM은 디스크로부터의 I/O를 해결해 줄 만한 캐시나 버퍼링 기능도 갖고 있지 않다
운영체제의 캐시 기능은 InnoDB보다 떨어지지만 없는 것 보다는 낫다
여유 메모리가 없을 시 MyISAM 테이블에 대한 쿼리 처리가 느려질 수 있다
InnoDB: 프라이머리 키에 의해서 클러스터링되어 저장
MyISAM: 프라이머리 키에 의한 클러스터링 없이 힙 공간처럼 활용
로그 파일로 상태나 부하 원인을 쉽게 찾을 수 있다
MySql 설정 파일에서 log_error라는 이름의 파라미터로 정의된 경로에 생성
별도로 정의되지 않은 경우에는 데이터 디렉터리에 .err라는 확장자가 붙은 파일로 생성
다음 정보들을 포함
general_log_file이라는 이름의 파라미터에 설정이 되어 있다
SHOW GLOBAL VARIABLES LIKE 'general_log_file';
슬로우 쿼리 로그 파일에는 long_query_time 시스템 변수에 설정한 시간 이상의 시간이 소요된 쿼리가 모두 기록된다
정상적으로 실행되고 스레시 홀드를 넘긴 쿼리들만 기록이 된다
pt-query-digest 명령 실행 시 —order-by 옵션으로 정렬 순서를 변경할 수 있다