mysql 11

Real MySQL 8.0 스터디 회고

13주 동안 진행한 Real MySQL 8.0 스터디에 대해 회고하는 글입니다. 스터디 방식은 1) 매주 정해진 학습 범위에 대해 Real MySQL 8.0 교재를 읽고, 2) 해당 범위와 관련된 나만의 주제를 정해 블로그 글을 작성하고, 3) 스터디 미팅 시간에 각자의 주제에 대해 발표 및 질의응답 시간을 가졌습니다. 추가적으로 4) 논의할만한 주제를 각자 가져와서 서로 질문하고 답변하는 시간도 가졌습니다. 스터디를 시작할 때 세웠던 목표를 돌아보고, 잘한 점과 개선할 점을 생각해보았습니다. 처음에 세웠던 목표는 다음과 같습니다. MySQL 동작 원리 이해하기 MySQL의 다양한 기능 써보기 나의 생각과 고민이 들어간 글을 꾸준히 작성하기 발표, 토론 스킬 향상시키기 각각의 목표를 얼마나 달성하였는지에..

회고 2024.04.11

[MySQL] 쿼리 성능 확인하기 - Performance 스키마 & Sys 스키마

MySQL에서 제공하는 Performance 스키마와 Sys 스키마를 활용하면 현재 데이터베이스의 상태를 확인하고, 성능을 향상시킬 수 있는 튜닝 요소들을 찾을 수 있다. 마침 진행중인 프로젝트에서 E2E 테스트를 위해 실행 중인 MySQL 서버가 있어서 쿼리 성능을 확인해보기로 했다. 이번 시간에는 서버에서 자주 실행되는 쿼리 목록과 실행 시간이 긴 쿼리 목록을 확인해 볼 것이다. 자주 실행되는 쿼리 목록 확인 Sys 스키마의 statement_analysis 뷰를 통해 확인할 수 있다. 어느 데이터베이스에서 실행된 쿼리인지(db), 실행 횟수(exec_count), 그리고 쿼리문(query)을 실행 횟수 내림차순으로 정렬하여 출력하도록 쿼리를 작성했다. 프로젝트 관련한 쿼리만 조회하기 위해 WHERE..

[MySQL] InnoDB 클러스터

InnoDB 클러스터란? MySQL에서 제공하는 고가용성(High Availability) 솔루션이다. 즉 MySQL의 가용성을 높이기 위한 기능이다. 어떻게 가용성을 높이는 걸까? MySQL의 일반 복제(Replication) 기능을 통해 소스-레플리카 구조로 형성하는 것도 가용성을 높이기 위한 하나의 방법이다. 다만 이러한 일반 복제는 소스 서버에서 장애 발생시 레플리카 서버가 자동으로 기존의 소스 서버를 대체하는 기능(Failover)을 제공하지는 않는다. 이를 자동화하기 위해 InnoDB 클러스터를 사용할 수 있다. ❓ Failover란? 장애 극복 기능을 의미하며, 시스템에 이상이 생겼을 때 대체 시스템으로 자동 전환하는 기능이다. 어떻게 장애 극복을 자동화하는 걸까? InnoDB 클러스터는 다..

[MySQL] 데이터베이스 복제(Replication)

복제(Replication)란? 한 서버에서 다른 서버로 데이터가 동기화 되는 것을 의미 원본 데이터를 가진 서버를 소스 서버(Source), 복제된 데이터를 가진 서버를 레플리카 서버(Replica)라고 한다. 데이터베이스 복제 과정 소스 서버의 바이너리 로그를 기반으로 복제한다. 바이너리 로그란? MySQL 서버에서 발생하는 모든 변경사항(이벤트)이 순서대로 기록되는 로그 파일. 데이터베이스 변경 내역, 데이터베이스나 테이블의 구조 변경, 계정이나 권한 변경 등이 기록된다. 복제 순서 소스 서버의 바이너리 로그 덤프 스레드는 바이너리 로그를 레플리카 서버로 전송한다. 레플리카 서버의 레플리케이션 I/O 스레드는 소스 서버의 바이너리 로그 덤프 스레드로부터 바이너리 로그 이벤트를 가져와 로컬 서버의 파..

[MySQL] DATETIME vs. TIMESTAMP

MySQL에서 날짜와 시간 정보를 저장하기 위한 여러가지 데이터 타입이 있다. 그 중에서 날짜와 시간을 합쳐서 하나의 칼럼에 저장할 수 있는 데이터 타입은 DATETIME과 TIMESTAMP이다. DATETIME과 TIMESTAMP의 차이점과 각각의 장단점을 알아보기 위해, 날짜와 시간 타입에서 발생할 수 있는 2가지 문제를 중심으로 살펴보려고 한다. 바로 타임존 문제와 Y2K38 문제이다. 타임존(timezone) 문제 타임존은 지구 상의 서로 다른 지역의 시차로 인해 온라인 상에서 시간의 불일치가 발생하는 것을 해결하기 위한 수단이다. 타임존을 표현할 때는 UTC 시간을 기준으로 하며, 한국 시간의 경우 UTC+09:00 시간대로 표현된다. UTC+00:00 타임존으로 표현된 시간 값을 한국에서 표시..

[MySQL] 온라인 DDL

온라인 DDL이란? DDL(Data Definition Language)은 데이터를 정의하는 언어로, 데이터베이스의 구조를 변경하는 쿼리를 의미한다. 테이블을 생성하거나 변경하는 등의 쿼리가 이에 해당한다. 온라인 DDL은 테이블의 스키마를 변경하는 작업이 실행되는 중에도 다른 커넥션에서 해당 테이블의 데이터를 조회하거나 변경하는 작업을 가능하게 한다. MySQL 8.0 버전부터는 대부분의 스키마 변경 작업에 대해 MySQL 서버에 내장된 온라인 DDL 기능을 이용하는 것이 가능해졌다. 온라인 DDL 알고리즘 ALGORITHM과 LOCK 옵션을 이용해 어떤 알고리즘으로 스키마를 변경할 지 결정할 수 있다. MySQL 서버는 다음 순서로 스키마 변경에 적합한 알고리즘을 찾는다. ALGORITHM=INSTA..

[MySQL] 실행 계획 확인하는 명령어

MySQL 옵티마이저는 사용자가 요청한 쿼리를 최소 비용으로 실행하기 위한 실행 계획을 세운다. 그러나 옵티마이저가 언제나 최적의 실행 계획을 수립할 것이라는 보장은 없으므로, MySQL 서버는 사용자가 실행 계획을 확인하고 보완할 수 있는 방법을 제공한다. 이번 시간에는 MySQL 옵티마이저가 쿼리에 대해 세운 실행 계획을 확인하는 다양한 명령어에 대해 알아보자. EXPLAIN / DESC / DESCRIBE EXPLAIN, DESC, DESCRIBE 명령어를 사용하면 실행계획을 테이블 형태로 확인할 수 있다. EXPLAIN SELECT * FROM employees e INNER JOIN salaries s ON s.emp_no=e.emp_no WHERE first_name='Matt'; 실행 결과 ..

[MySQL] 옵티마이저의 선택은? 네스티드 루프 조인 vs. 해시 조인

MySQL 데이터베이스에서 쿼리를 최적화하는 과정에서 옵티마이저는 다양한 결정을 내려야 한다. 그 중 하나는 Join과 관련한 최적화이다. 이번 시간에는 네스티드 루프 조인(Nested Loop Join)과 해시 조인(Hash Join)에 대해 살펴보고, 상황에 따라 옵티마이저가 어떤 조인 방식을 선택하는지 알아보자. 네스티드 루프 조인 아래와 같이 2개의 테이블을 조인하는 예시를 들어보자. member 테이블은 회원 정보를 가지고 있으며, salary 테이블은 from_date와 to_date 사이의 기간에 회원이 받은 급여 정보를 가지고 있다. 2개의 테이블을 조인할 때 먼저 조회되는 테이블을 드라이빙 테이블(driving table), 나중에 조회되는 테이블을 드리븐 테이블(driven table)..

[MySQL] 프라이머리 키가 일반 인덱스보다 특별한 이유 - InnoDB 클러스터링 인덱스

프라이머리 키(PK)는 테이블에 하나밖에 없는 값이다. 오늘은 프라이머리 키가 왜 특별한지, 다른 키(인덱스)와의 차이는 무엇인지 알아보자. 참고로 이 글에서는 키(key)와 인덱스(index)를 같은 의미로 사용한다. InnoDB 클러스터링 인덱스 프라이머리 키의 중요성을 알기 위해서는 프라이머리 키가 클러스터링 인덱스라는 것부터 시작해야한다. 클러스터링 인덱스란 프라이머리 키 값이 비슷한 레코드끼리 묶어서 저장하는 것을 의미한다. 프라이머리 키 값에 의해 레코드의 물리적인 저장 위치가 결정되는 것이다. MySQL에서 클러스터링 인덱스는 InnoDB 스토리지 엔진에서만 지원한다. 프라이머리 키를 기준으로 데이터가 물리적으로 정렬되어 있기 때문에 프라이머리 키 기반의 검색이 매우 빠른 장점이 있다. 대신..

[MySQL] InnoDB 인덱스 잠금 테스트

InnoDB는 레코드 기반의 잠금 방식을 사용하는데, 중요한 점은 레코드 자체를 잠그는 것이 아니라 인덱스를 잠근다는 것이다. 이 부분은 잘못 설계하면 데이터베이스 성능에 큰 영향을 미칠 것 같아 확실히 알아보기 위해 테스트를 진행해보기로 했다. 먼저 전체적인 시나리오를 설명하면 (first_name, last_name, age) 속성을 가지는 member 테이블을 만들고 last_name 속성에 인덱스를 설정했다. 테이블에 저장된 ‘김민수’ 회원의 나이를 바꾸기 위해 UPDATE하는 트랜잭션을 시작하였다. 이 경우, 동시에 다른 ‘김’씨 성을 가진 회원 정보를 수정할 수 있을까? 얼핏 생각하면 ‘김민수’ 회원 한명의 레코드를 수정하고 있는 것 뿐인데, 김민수 회원이 아닌 다른 ‘김’씨 성을 가진 회원의..