MySQL 아키텍쳐
- MySQL 접속 클라이언트
- MySQL 엔진 (접속과 요청 처리)
- 전처리기
- 옵티마이저 (실행계획 만듦)
- 캐시
- MySQL 스토리지 엔진 (손발 역할)
- 데이터를 실제로 디스크에 저장하고, 이를 읽어옴
- MySQL 엔진이랑 연결되는걸 핸들러 API라고 함
- OS
쿼리 실행 과정
1. 쿼리 캐싱
- 동일한 요청이라면 바로 응답
- 근데 이게 테이블 변경되면 삭제해야겠지?
- 그러면 이게 락이 걸리겠지? 성능 악화되겠지? 8.0부턴 삭제댓어
2. 쿼리 파서
3. 전처리기
- Parse tree를 기반으로 SQL의 문장 구조를 체크
- Parse tree의 토큰이 유효한지 확인
4. 옵티마이저
- SQL 실행을 최적화해서 실행 계획 수립
- 규칙 기반 최적화: 옵티마이저 내장 우선 순위에 따라 실행 계획
- 비용 기반 최적화: 작업의 비용과 대상 테이블의 통계를 가지고 실행계획
5. 쿼리 실행 엔진
- 실행계획 가지고 접근
6. 스토리지 엔진
- 핸들러 API에 의해 동작
- 쿼리 실행 엔진이 요청하는대로 데이터 디스크로 저장/읽기
InnoDB 스토리지 엔진
- 요즘은 이게 MySQL 기본 엔진~! (From MySQL 5.7)
- PK에 의한 클러스터링
- PK순으로 레코드를 저장
- PK 인덱스 자동 생성
- PK를 통한 범위 검색 빠름
- 클러스터링 때문에 쓰기 성능 저하
- InnoDB에서 PK 안 쓰면 알아서 혼자 만들어줌
- 근데 접근은 안되는,,,
- 트랜잭션 지원
- MVCC
- 트랜잭션 격리 수준에 따라 조회되는 데이터가 달라져요~!
- 업데이트 하고 있는 상황 사이에, 해당 레코드 조회 요청이 온다면??!
- InnoDB 버퍼풀 (READ_UNCOMMITED)
- 업데이트 하면 바뀐거 즉각 저장
- 언두 로그 (READ_COMMITED, REAPEATABLE_READ)
- 업데이트 하면 그 전꺼 언두로그에 저장해둬
- 레코드 단위 잠금
- 레코드 잠그는게 아니라, 인덱스를 잠금
- 동시 처리 성능이 좋음
- 버퍼풀
- 데이터 캐싱
- 페이지 단위로 테이블 데이터 관리
- 쓰기 지연 버퍼
- 변경된 데이터를 버퍼풀에 모았다가 한번에 디스크에 기록 (Random IO 최소화)
- 어댑티브 해시 인덱스
- 페이지에 빠르게 접근하기 위한 해시 자료구조 기반 인덱스
MyISAM 스토리지 엔진
- 클러스터링 지원 X
- 트랜잭션 지원 X
- 외래키 지원 X
- 테이블 단위 잠금
- 키 캐시 사용
Lock이란?
- Lock이 없다면 데이텀 무결성 및 일관성이 깨짐
- 여러 사용자들의 동시성 제어를 위해 필요!
Lock의 종류?
- 벤더사마다 다른 Lock의 종류와 전략들
- InnoDB에 초점
1. 배타 잠금 (Exclusive Locks )
- select * from information_schema.INNODB_LOCKS 로 락 걸린 레코드 확인 가능
- write에 대한 lock
- select for update, dleete 수정 쿼리 ㅈ날릴때 row에 걸리는 lock
2. 공유 잠금 (Shared Locks )
- select * from booth where name = 'botobo' lock in share lock
- read에 대한 lock
- read 작업 수행시 사용
3. 레코드 락
- row가 아닌 DB index record에 걸리는 lock
- 인덱스에 없다면...?
- 테이블내의 숨겨져있는 클러스터드 인덱스에 걸어버려
4. 갭락
- index record의 gap에 걸리는 lock
- gap이란 index record가 없는 부분
- 조건에 해당하는 새로운 row가 추가되는 것을 방지하기 위함
DB Deadlock 예제
- 1번이 xlock 걸고, 3번이 xlock 걸고
- 1번은 3번으로 옮길라하고, 3번을 1번으로 옮길라고함
- 둘이 싸우네? Deadlock 발생
- SHOW ENGINE INNODB STATUS : 최근 데드락 발생 알려줌