서론
위 글은 최근 읽었던 개발자를 위한 Redis란 책을 요약 겸 복습하기 위해 정리한 글입니다. 참고로 최신 버전인 8.0 버전이 아닌, 5.7 버전 기준으로 작성되었음을 말씀 드립니다.

핵심요약
- MySQL 기본 개념
- 관계형 데이터베이스(RDBMS)란 무엇이며, MySQL은 어떤 특징을 가지는가?
- MySQL과 다른 RDBMS(예: PostgreSQL, Oracle)와의 차이점은 무엇인가?
- MySQL의 주요 데이터 타입(정수, 문자열, 날짜 등)은 어떤 것들이 있고, 언제 어떤 타입을 선택해야 하는가?
- MySQL의 기본적인 SQL 문법(SELECT, INSERT, UPDATE, DELETE)은 어떻게 동작하는가?
- 인덱스(Index)와 성능 최적화
- 인덱스란 무엇이며, 어떤 원리로 데이터 조회 성능을 향상시키는가?
- B-Tree 인덱스와 Hash 인덱스의 차이점은 무엇인가?
- 커버링 인덱스(Covering Index)와 복합 인덱스(Composite Index)는 어떻게 활용하는가?
- 인덱스를 너무 많이 사용하면 어떤 문제가 발생할 수 있는가?
- 트랜잭션과 동시성 제어
- 트랜잭션(Transaction)이란 무엇이며, ACID 특성은 각각 무엇을 의미하는가?
- MySQL에서 트랜잭션을 지원하는 스토리지 엔진(InnoDB, MyISAM 등)의 차이점은?
- 트랜잭션 격리 수준(READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE)은 어떤 차이가 있는가?
- InnoDB의 MVCC(Multi-Version Concurrency Control)는 어떻게 동작하며, 어떤 장점이 있는가?
- Deadlock(교착 상태)은 어떻게 발생하며, 이를 방지하거나 해결하는 방법은?
- 조인(Join)과 쿼리 최적화
- INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN의 차이점은?
- Nested Loop Join, Hash Join, Sort-Merge Join 등 MySQL의 조인 방식은 어떻게 동작하는가?
- MySQL에서 서브쿼리보다 조인을 권장하는 이유는?
- 실행 계획(EXPLAIN)을 분석하는 방법과 주요 항목(EXPLAIN의 type, key, rows 등)은 무엇인가?
- 저장 구조와 내부 동작 원리
- MySQL의 데이터 파일과 로그 파일의 구조는 어떻게 구성되는가?
- MySQL의 Redo Log, Undo Log, Binary Log는 각각 어떤 역할을 하는가?
- 데이터가 실제로 디스크에 저장되는 방식과 버퍼 풀(Buffer Pool)의 역할은?
- Auto Increment(자동 증가) 필드는 내부적으로 어떻게 동작하는가?
- MySQL 확장성과 분산 처리
- 샤딩(Sharding)과 파티셔닝(Partitioning)의 차이점은 무엇인가?
- MySQL 복제(Replication) 방식(Semi-Synchronous, Asynchronous, GTID 등)의 차이점은?
- MySQL에서 Read Replica를 활용하는 방법과 한계점은?
- MySQL Cluster와 Galera Cluster는 어떤 원리로 다중 노드 환경을 구성하는가?
- MySQL 운영 및 유지보수
- 데이터베이스 백업과 복구 전략(물리적 백업 vs 논리적 백업, Point-in-Time Recovery)은 어떻게 구성해야 하는가?
- 데이터베이스 테이블 설계 시 정규화(Normalization)와 반정규화(Denormalization)의 트레이드오프는?
- MySQL에서 대량 데이터를 삽입/삭제할 때 주의할 점은?
- 주기적인 테이블 분석(ANALYZE TABLE)과 최적화(OPTIMIZE TABLE)의 역할은?
1. MySQL 기본 개념
관계형 데이터베이스(RDBMS)란 무엇이며, MySQL은 어떤 특징을 가지는가?
관계형 데이터베이스라면 대표적으로 Oracle, MySQL이 있다. 이 중에서도 대기업, 금융 IT 계열이 아닌 이상 MySQL을 사용하는 경우가 많기 떄문에, RDBS는 곧 MySQL를 떠올리는 경우가 많다. MySQL의 상위 카테고리인 RDBMS란 무엇이며, 어떤 특징을 가질까?
관계형 데이터베이스(RDBMS, Relational Database Management System)는 데이터를 테이블(table) 형태로 저장하고, 행(row)과 열(column)을 이용해 관리하는 데이터베이스 시스템이다. 관계형 데이터베이스는 데이터를 관계(relation)를 기반으로 정리하고, SQL(Structured Query Language)을 사용해 데이터를 삽입, 조회, 수정, 삭제할 수 있다.
RDBMS의 주요 개념
- 테이블(Table): 데이터를 저장하는 기본 단위. 엑셀의 시트(sheet)와 유사하다.
- 행(Row, Tuple, Record): 테이블의 한 줄을 의미하며, 하나의 데이터 항목을 나타낸다.
- 열(Column, Field, Attribute): 테이블에서 각 데이터의 속성을 정의하는 요소이다.
- 기본 키(Primary Key): 각 행을 고유하게 식별하는 컬럼. 중복이 없어야 한다.
- 외래 키(Foreign Key): 다른 테이블의 기본 키를 참조하는 컬럼. 테이블 간 관계를 정의하는 데 사용된다.
- 정규화(Normalization): 데이터 중복을 최소화하고 무결성을 유지하기 위해 테이블을 구조적으로 정리하는 과정이다.
MySQL의 특징
MySQL은 대표적인 오픈 소스 관계형 데이터베이스 관리 시스템(RDBMS)으로, 전 세계에서 가장 널리 사용되는 데이터베이스 중 하나이다. Oracle 대신 MySQL을 사용하는 가장 큰 이유는 가격과 비용일 것이다. 오라클 DBMS를 사용하는 회사는 모두 대형 엔터프라이즈 장비를 구매하고 값비싼 스토리지를 도입해서 분산돼 있던 데이터를 모두 하나의 장비로 긁어모으는 통합(컨솔리데이션) 위주로 데이터를 관리해왔다. 이러한 관리 방식의 장점은 분산된 데이터를 애플리케이션에서 조회하지 않아도 되므로 개발 생산성이 높아진다는 점이다. 그렇지만 이는 동시에 큰 단점이다. 위험이 집중되고 장애의 범위가 여러 서비스로 확산되는 역효과가 발생된다. 반면 MySQL은 태생부터 고급 엔터프라이즈급 장비가 아니다. 그래서인지 MySQL은 소규모 장비를 확장(Scale-out)해서 사용하는 데 주력해왔다. MySQL의 복제 구성은 오라클과 비교할 수 없이 간단하고 유연하다.
MSSQL과 비교해도, 비용 면에서 장점이 있고 윈도우 서버에서만 사용할 수 있는 MSSQL과 다르게, MySQL은 다양한 플랫폼에서 사용할 수 있다는 장점이 있다.
MySQL의 주요 특징
- 오픈소스 및 상용 버전 제공
- MySQL은 GPL(General Public License) 기반의 오픈 소스 DBMS이지만, Enterprise Edition(상용 버전)도 제공된다.
- 무료로 사용할 수 있는 Community Edition과 성능 및 보안 기능이 추가된 Enterprise Edition이 있다.
- 다양한 운영체제 (OS) 지원
- Windows, macOS, Linux, UNIX 등 대부분의 운영 체제에서 실행 가능하다.
- 컨테이너(Docker) 환경에서도 쉽게 배포할 수 있다.
- 높은 성능과 확장성
- InnoDB 스토리지 엔진을 기반으로 트랜잭션과 동시성을 지원하여 안정적인 성능 제공한다.
- 대규모 트래픽을 처리하기 위한 Replication(복제), Sharding(샤딩) 기능 제공한다.
- 읽기(Read) 성능이 뛰어나서 웹 서비스(WordPress, Magento 등)에 많이 사용된다.
- 다양한 스토리지 엔진 지원
- MySQL은 여러 가지 스토리지 엔진을 지원하여 유연한 데이터 저장 방식을 선택할 수 있다.
- InnoDB : 기본 스토리지 엔진 (5.6 버전 이상), ACID 및 트랜잭션 지원, 외래 키 사용 가능
- MyISAM : 트랜잭션 미지원, 빠른 읽기 성능, 작은 데이터베이스에 적합
- Memory(Heap) : 데이터를 메모리에 저장하여 매우 빠른 읽기/쓰기 속도 제공
- CSV : 데이터를 CSV 파일로 저장, 다른 시스템과 연동 용이
- Archive : 대량 데이터 압축 저장, 로그 저장에 적합
- NDB Cluster : 분산 데이터베이스 엔진, 고기용성(HA) 지원
- MySQL은 여러 가지 스토리지 엔진을 지원하여 유연한 데이터 저장 방식을 선택할 수 있다.
- 강력한 트랜잭션 및 동시성 지원
- InnoDB 엔진에서 ACID(Atomicity, Consistency, Isolation, Durability) 트랜잭션을 보장.
- MVCC(Multi-Version Concurrency Control)를 사용하여 동시성을 유지하며 락 경합(lock contention)을 줄임.
- SQL 표준 준수 및 풍부한 기능 제공
- ANSI SQL 표준을 기반으로 하지만, MySQL만의 확장 기능도 포함됨.
- 저장 프로시저(Stored Procedure), 트리거(Trigger), 이벤트(Event), 뷰(View) 등 다양한 기능 제공.
- JSON 데이터 타입 및 NoSQL과 유사한 기능도 일부 지원.
- 복제(Replication) 및 고가용성(HA) 지원
- 마스터-슬레이브(Master-Slave) 복제 및 마스터-마스터(Multi-Primary) 복제 지원.
- GTID(Global Transaction ID)를 활용한 간편한 복제 설정 가능.
- MySQL Cluster 및 Galera Cluster를 이용해 고가용성 구성 가능.
- 대규모 데이터 처리 가능
- 샤딩(Sharding)을 활용하여 수평 확장 가능.
- 파티셔닝(Partitioning) 기능을 사용해 대량 데이터를 효율적으로 관리.
- 커뮤니티 & 생태계 지원
- MySQL은 전 세계적으로 가장 인기 있는 데이터베이스 중 하나로, 방대한 사용자 커뮤니티가 존재함.
- MySQL Workbench와 같은 GUI 도구 지원.
- Amazon RDS(MySQL), Google Cloud SQL, Azure Database for MySQL과 같은 클라우드 서비스에서도 널리 사용됨.
MySQL과 다른 RDBMS(예: PostgreSQL, Oracle)와의 차이점은 무엇인가?

각 Database를 선택하는 기준을 정리하면 아래와 같다.
- MySQL
- 읽기 성능이 우수하며, 웹 서비스에 적합
- MySQL은 단순한 SELECT 쿼리에서 뛰어난 성능을 보이며, Read Replica를 쉽게 확장할 수 있음
- 하지만 PostgreSQL은 고급 인덱스와 최적화 기능이 더 뛰어나므로 복잡한 쿼리에서 더 나은 성능을 제공함
- Oracle은 OLAP 및 대규모 트랜잭션 환경에서 최고의 성능을 발휘하지만, 비용이 매우 높음
- 클라우드 환경에서 간편하게 운영하고 싶을 때
- 설치가 빠르고 가벼운 구조 → 최소한의 리소스로 실행 가능
- AWS RDS, GCP Cloud SQL 등과 높은 호환성 → 자동 백업 및 모니터링 지원
- Read Replica 기능으로 손쉽게 읽기 확장 가능 → 간단한 복제 설정으로 트래픽 분산
- 운영 비용이 저렴하고 유지보수가 쉬움 → 관리 부담이 적고 무료 버전 활용 가능
- 복잡한 기능보다 빠른 개발이 필요할 때
- 쉬운 설치 & 설정 → 개발 환경을 빠르게 구성 가능
- 직관적인 SQL 문법 & ORM 지원 → 다양한 개발 프레임워크와 쉽게 연동 가능
- 스타트업 및 중소기업에서 많이 사용 → 학습 자료가 많고, 지원이 활발함
- 기본적인 웹 서비스에는 충분한 기능 제공 → 복잡한 기능 없이도 효율적으로 개발 가능
- 읽기 성능이 우수하며, 웹 서비스에 적합
- PostgreSQL
- SQL 표준을 준수하며, 데이터 무결성이 중요한 서비스(금융, 정부, 의료)에 적합
- ANSI SQL 표준을 가장 엄격하게 준수하는 RDBMS로, MySQL이나 Oracle보다 더욱 정밀한 SQL 호환성을 제공
- PostgreSQL은 CHECK, FOREIGN KEY, UNIQUE, NOT NULL 등의 강력한 제약 조건을 제공하여 데이터의 무결성을 보장함
- PostgreSQL은 MVCC(Multi-Version Concurrency Control)을 사용하여, 트랜잭션이 서로 영향을 주지 않고 동시에 실행 가능
- JSON, GIS, 대규모 데이터 처리(OLAP, BI)
- PostgreSQL은 JSON 및 JSONB(Binary JSON) 데이터 타입을 기본 제공하여 NoSQL과 유사한 기능을 제공함. JSONB는 바이너리 형태로 저장되어 검색 속도가 빠르고, 인덱싱이 가능하여, NoSQL 기능과 RDBMS의 장점을 결합한 형태.
- PostgreSQL은 PostGIS 확장을 통해 강력한 GIS(Geospatial) 기능을 제공, 공간 데이터를 저장하고, 복잡한 공간 연산(거리 계산, 다각형 포함 여부 등)을 수행할 수 있음.
- 복잡한 트랜잭션 및 고급 SQL 기능을 활용할 때
- PostgreSQL은 모든 쿼리를 기본적으로 트랜잭션 내에서 실행하며, COMMIT 또는 ROLLBACK이 가능함
- 강력한 JOIN 성능 → PostgreSQL은 Nested Loop, Hash Join, Merge Join을 활용해 복잡한 JOIN 쿼리를 최적화
- 확장성이 뛰어난 오픈 소스 솔루션을 원할 때
- Multi-Master Replication, 샤딩, 파티셔닝을 통한 대규모 확장 지원 : MySQL은 기본적으로 읽기 복제(Read Replica)만 지원하여, 쓰기 확장에는 다소 불리함, Oracle도 멀티 마스터 기능을 제공하지만, 유료 라이선스를 요구하며 비용이 매우 높음
- SQL 표준을 준수하며, 데이터 무결성이 중요한 서비스(금융, 정부, 의료)에 적합
- Oracle
- 엔터프라이즈급 DB로, 대규모 트랜잭션과 대량 데이터 분석(OLAP) 및 고급 인덱싱 제공하지만 비용이 높음
- 뛰어난 트랜잭션 처리 및 확장성
- Parallel Query(병렬 쿼리 실행): 대량 데이터를 빠르게 처리할 수 있도록 여러 CPU 코어를 활용하여 병렬 실행 최적화
- Advanced Queueing(AQ) 지원: 대량 트랜잭션 처리를 위해 메시징 큐 방식으로 트랜잭션을 비동기적으로 처리 가능
- Automatic Storage Management(ASM): 대규모 데이터를 자동으로 관리하며, 스토리지 성능을 최적화함
- 대량 데이터 분석(OLAP) 및 고급 인덱싱 기능 제공
- Bitmap Index: OLAP(온라인 분석 처리) 환경에서 읽기 성능을 최적화하며, 대량 데이터에 대한 복잡한 쿼리를 최적화
- Materialized View: 자주 사용하는 쿼리를 미리 저장하여 대규모 분석 쿼리를 빠르게 실행 가능
- Partitioning(파티셔닝): 데이터베이스 테이블을 물리적으로 나누어 대량 데이터 분석 성능을 향상
- 뛰어난 트랜잭션 처리 및 확장성
- 미션 크리티컬한 엔터프라이즈 시스템(대기업, 은행, ERP)
- 강력한 고가용성(HA, High Availability) 솔루션 지원
- Oracle RAC(Real Application Clusters): 여러 서버에서 단일 데이터베이스를 공유하여 무중단 운영을 보장
- Oracle Data Guard: 장애 발생 시 자동으로 Standby Database로 전환하여 즉시 복구 가능
- Flashback Technology: 실수로 데이터를 삭제하거나 변경해도 과거 상태로 쉽게 복구 가능
- 금융 및 ERP 시스템에 특화된 강력한 보안 및 감사 기능
- TDE(Transparent Data Encryption): 데이터를 저장할 때 자동으로 암호화하여 보안성을 강화
- Fine-Grained Auditing(FGA): 데이터베이스 접근을 세밀하게 감사 가능하여 보안 규제 준수(GDPR, HIPAA 등)
- Row-Level Security(RLS): 사용자 권한에 따라 테이블의 특정 행(Row)만 접근 가능하도록 설정 가능
- 강력한 고가용성(HA, High Availability) 솔루션 지원
- 초고성능 데이터베이스가 필요한 경우
- 초고성능 트랜잭션을 위한 고급 기능
- Exadata 전용 하드웨어: Oracle Exadata는 OLTP 및 OLAP 환경을 위한 초고속 데이터베이스 하드웨어로, 일반적인 DBMS보다 10배 이상 빠른 성능을 제공
- Multi-Version Read Consistency (MVRC): 동시성을 유지하면서 쓰기 성능을 극대화하여 대량 트랜잭션 처리 가능
- Memory-Optimized Tables: 데이터를 메모리에서 직접 처리하여 I/O 속도를 획기적으로 줄임
- 분산 처리 및 샤딩 지원
- Oracle Sharding: 데이터를 여러 노드에 분산 저장하여 수평 확장(Scale-Out)을 지원
- Hybrid Columnar Compression (HCC): 데이터를 컬럼 기반으로 압축하여 저장 공간을 절약하고, 분석 속도를 높임
- 초고성능 트랜잭션을 위한 고급 기능
- 비용이 문제가 되지 않으며, 강력한 공식 지원이 필요할 때
- 글로벌 수준의 공식 지원 및 SLA 보장
- Oracle Premier Support: 24/7 기술 지원을 제공하며, 기업 SLA(Service Level Agreement)를 철저히 준수
- 기업 맞춤형 컨설팅 지원: Oracle 전문가가 직접 데이터베이스 성능 튜닝 및 유지보수 지원
- 장기적인 안정적인 버전 지원: 일부 오픈 소스 DB는 업데이트 중단될 수 있지만, Oracle은 장기간 버전 지원을 보장
- 엔터프라이즈 라이선스를 통한 최적화된 성능 제공
- 비용이 높지만, 기업에서는 비용보다 시스템 안정성과 성능을 우선 고려해야 하므로 Oracle을 선택
- SAP, Oracle ERP, Salesforce, 금융권 시스템 등 엔터프라이즈 환경에서 최적화된 DBMS로 활용됨
- 글로벌 수준의 공식 지원 및 SLA 보장
- 엔터프라이즈급 DB로, 대규모 트랜잭션과 대량 데이터 분석(OLAP) 및 고급 인덱싱 제공하지만 비용이 높음
MySQL의 주요 데이터 타입(정수, 문자열, 날짜 등)은 어떤 것들이 있고, 언제 어떤 타입을 선택해야 하는가?
MySQL에서 데이터 타입을 잘 선택하면 성능, 저장 공간, 검색 속도를 최적화할 수 있다. 데이터 타입은 크게 정수, 실수, 문자열, 날짜/시간, JSON, 기타로 나뉜다.
- 정수(Integer) 타입

- TINYINT → 작은 숫자(예: Boolean 값 0/1 저장, 상태 플래그)
- SMALLINT → 최대 6만 개의 ID 저장(예: 카테고리 ID, 작은 목록)
- MEDIUMINT → 중간 크기의 정수(예: 사용자 ID, 주문 번호)
- INT → 일반적인 숫자 데이터(예: 기본 키, 인덱스 필드)
- BIGINT → 큰 숫자(예: SNS에서 사용자 수, 금융 트랜잭션 데이터)
- 실수(Floating-Point) 타입

- FLOAT → 속도가 중요한 경우 (예: 그래픽, 센서 데이터)
- DOUBLE → 더 높은 정밀도가 필요한 경우
- DECIMAL → 금융/통화 데이터(정확한 계산 필요)
- 문자열 타입

- CHAR → 길이가 일정한 데이터(예: 국가 코드 KR, US)
- VARCHAR → 일반적인 문자열 데이터(예: 사용자 이름, 이메일), 실제 사용 가능한 VARCHAR 크기는 16,384자(UTF-8 기준, 한 글자당 4바이트)가 한계이다.
- TEXT → 긴 글 저장(예: 블로그 내용, 댓글)
- BLOB → 이미지, PDF 같은 바이너리 데이터 저장
1) 긴 텍스트 저장 (TEXT 계열)

- MySQL에서 TEXT 또는 BLOB 데이터를 최적화하여 조회하는 방법
- VARCHAR(255) vs TEXT 성능 차이
- VARCHAR(255) → 테이블 내부 저장, 빠른 검색
- TEXT → 외부 저장, 긴 데이터 저장 가능하지만 검색 속도가 느림
- TEXT/BLOB 성능 최적화 방법
- FULLTEXT 인덱스 활용 (MATCH() AGAINST())
- TEXT/BLOB 컬럼을 별도 테이블로 분리
- Redis/Memcached로 캐싱
- SUBSTRING으로 필요한 부분만 조회
- VARCHAR(N)의 크기 제한
- 한 행(Row) 크기 제한(65,535바이트)으로 인해 VARCHAR(65535)는 비현실적
- utf8mb4 사용 시 한 글자당 최대 4바이트 차지 → VARCHAR(16,384) 정도가 한계
- VARCHAR(255) vs TEXT 성능 차이
- FULLTEXT 검색 vs 일반적인 LIKE 검색 차이점
- LIKE 검색 : 단순한 부분 문자열 검색을 수행하는 방법으로, 주로 % 와 _ 와일드카드를 사용하여 특정 패턴과 일치하는 값을 찾을 수 있다.
- 한계점
- 인덱스를 사용할 수 없음 (앞쪽 % 사용 시) → 테이블 풀스캔 발생 (O(n))
- 검색 성능이 낮음 → 데이터가 많아질수록 속도가 급격히 저하됨
- 자연어 검색(동의어, 복수형 등) 미지원
- 한계점
- FULLTEXT 검색 : 자연어 기반의 인덱싱을 사용하여 빠른 검색을 제공하는 방법
- 장점
- 빠른 검색 속도 → LIKE 검색보다 훨씬 빠름
- 자연어 검색 가능 → 단순 패턴 매칭이 아니라 의미를 분석하여 검색
- 대용량 데이터에서 성능 우수 → 수백만 개의 레코드에서도 빠르게 검색 가능
- 가중치 검색 가능 → 특정 키워드에 가중치를 부여할 수 있음
- 한계점
- 최소 단어 길이 제한 → 기본적으로 4자 이상 단어만 검색 가능 (ft_min_word_len = 4)
- OR 연산이 어려움 → LIKE '%A%' OR LIKE '%B%' 같은 조합이 어려움
- 정확한 부분 문자열 검색이 어려움 → LIKE '%word%'처럼 일부 단어만 포함하는 검색이 불가능
- 장점
- LIKE 검색 : 단순한 부분 문자열 검색을 수행하는 방법으로, 주로 % 와 _ 와일드카드를 사용하여 특정 패턴과 일치하는 값을 찾을 수 있다.
- FULLTEXT INDEX를 사용할 시점 vs 검색 엔진 도입 시점
- FULLTEXT INDEX를 사용해야 하는 경우
- LIKE 검색의 성능이 너무 느려지는 경우
- 짧은 문장이 아닌 긴 텍스트(블로그, 리뷰, 뉴스 기사)를 검색해야 하는 경우
- 자연어 검색이 필요할 때
- MySQL 환경을 유지하면서 검색 속도를 최적화하고 싶을 때
- 검색 엔진(Elasticsearch, OpenSearch) 도입이 필요한 경우
- 데이터가 수백만~수억 개 이상으로 많아지면 MySQL의 FULLTEXT 성능이 한계에 도달함
- 다양한 언어(한국어, 중국어 등)를 검색해야 할 때
- 복잡한 검색 기능(동의어 처리, NLP, 문서 랭킹, 검색어 자동완성 등)이 필요할 때
- 검색과 데이터베이스 트랜잭션을 분리하고 싶을 때
- FULLTEXT INDEX를 사용해야 하는 경우
- FULLTEXT INDEX와 INSTANT 알고리즘
- FULLTEXT INDEX가 존재하는 테이블에서는 INSTANT 알고리즘을 사용할 수 없다. MySQL에서는 인덱스를 추가하거나 삭제할 때, 다음 3가지 알고리즘 중 하나를 사용하는데, INPLACE, INSTANT, COPY. 테이블에 FULLTEXT INDEX가 존재하면, 일반적인 B-TREE 인덱스를 추가/삭제할 때도 INSTANT를 사용할 수 없고 INPLACE 알고리즘이 사용된다. 이는 경우에 따라 성능 저하가 발생할 수 있다. 따라서 검색 기능이 중요하고 인덱스를 자주 변경해야 한다면, Elasticsearch 같은 전문 검색 엔진 도입을 고려해야 한다.
2) 바이너리 문자열 저장 (BLOB 계열)

- 날짜/시간(Date & Time) 타입

- DATE → 날짜만 저장 (예: 생년월일, 이벤트 날짜)
- DATETIME → 날짜와 시간을 함께 저장 (예: 주문 시간, 로그인 기록)
- TIMESTAMP → 시간대(UTC 변환) 필요할 때 사용 (예: 시스템 로그)
- JSON 및 기타 타입

- JSON → NoSQL처럼 데이터를 저장하고 싶을 때
- ENUM → 미리 정해진 값만 허용할 때 (예: ENUM('Male', 'Female'))
- SET → 여러 개의 선택지를 동시에 저장해야 할 때
MySQL의 기본적인 SQL 문법(SELECT, INSERT, UPDATE, DELETE)은 어떻게 동작하는가?
MySQL의 기본적인 SQL 문법은 CRUD(Create, Read, Update, Delete) 연산을 수행하는데 사용돼.
1) SELECT (데이터 조회)
SELECT * FROM users; -- 모든 행 조회
SELECT name, email FROM users WHERE age > 20; -- 특정 컬럼 조회 + 조건
SELECT COUNT(*) FROM orders WHERE status = 'completed'; -- 개수 조회
선택한 열만 조회 가능하고, WHERE 절로 조건을 지정할 수 있음.
2) INSERT (데이터 삽입)
INSERT INTO users (name, email, age) VALUES ('John Doe', 'john@example.com', 30);
테이블의 특정 열에 데이터를 추가할 때 사용.
3) UPDATE (데이터 수정)
UPDATE users SET email = 'newemail@example.com' WHERE id = 1;
WHERE 절을 지정하지 않으면 테이블의 모든 데이터가 변경될 수 있음(주의!).
4) DELETE (데이터 삭제)
DELETE FROM users WHERE id = 1;
WHERE 조건을 반드시 지정해야 함. 안 그러면 모든 데이터가 삭제됨.
2. 인덱스(Index)와 성능 최적화
인덱스란 무엇이며, 어떤 원리로 데이터 조회 성능을 향상시키는가?
- 정의
인덱스란 도서관의 책 찾기
와 같다. 도서관에 100만 권의 책이 있다고 가정했을 때, 책을 찾기 위해 한 권씩 처음부터 끝까지 살펴본다면 엄청 오래 걸릴 것이다. 그래서 도서관에는 책 목록
이 정리된 색인(Index)이 있는데, 책 제목이나 저자를 검색하면 해당 책이 어느 위치(서고, 칸, 번호)에 있는지 빠르게 찾을 수 있다.
데이터베이스에서도 동일하다.
SELECT * FROM books WHERE title = 'Harry Potter';
위 쿼리를 실행하면 책이 저장된 테이블에서 처음부터 끝까지 검색하면 느리지만, title
컬럼에 인덱스가 있으면 빠르게 찾을 수 있다.
- 동작 원리
쉽게 말해, 인덱스는 데이터베이스의 "색인(목차)" 역할을 한다.
books 테이블
-----------------------------------
| id | title | author |
-----------------------------------
| 1 | Harry Potter | J.K.Rowling |
| 2 | The Hobbit | J.R.R. Tolkien |
| 3 | 1984 | George Orwell |
| 4 | Moby-Dick | Herman Melville |
-----------------------------------
여기서 "Harry Potter"을 찾으려면 전체 테이블을 하나씩 검색해야 한다. (O(n) → 느림)
반면, title 칼럼에 인덱스를 적용하면 아래와 같다.
title 컬럼을 기준으로 인덱싱된 B+Tree 구조
[ Moby-Dick ]
/ \
[ 1984 ] [ The Hobbit ]
| |
[ 1984, id=3 ] [ The Hobbit, id=2 ]
- B+Tree는 트리 구조로 정렬되어 있어 빠르게 검색 가능
- 루트 → 왼쪽 or 오른쪽으로 이동하면서 O(log n) 탐색 성능 제공
- 다중 레벨을 가지며 균형을 유지하여 효율적인 검색을 수행함
- 리프노드에 데이터를 저장하고 있음
- 리프 노드 간 연결리스트로 이어져 있어 범위 검색 시, 좋은 성능을 보임
B-Tree 인덱스와 Hash 인덱스의 차이점은 무엇인가?
- B-Tree 인덱스란 전화번호부처럼 데이터를 정렬하는 방식이다.
(50)
/ \
(25) (75)
/ \ / \
(10) (30) (60) (90)
예를 들어 60을 검색하려면? 루트(50) → 75보다 작음 → 왼쪽(25~75)으로 이동하고 60을 찾음! (로그 탐색, O(log n))
- Hash 인덱스
사전에서 단어를 찾는 것처럼, 특정 값만 바로 찾을 때 사용한다.
Key → Hash Function → Index
---------------------------------
'John' → 101 → Row 5
'Alice' → 102 → Row 3
'Bob' → 103 → Row 8
---------------------------------
WHERE name = 'Alice' 실행하면? 해시 값(102) 계산 → 즉시 해당 위치(Row 3)로 이동! (O(1), 매우 빠름)

(MySQL 상에서 Hash 인덱스를 명시적으로 걸어줄 수 있을까?)
커버링 인덱스(Covering Index)와 복합 인덱스(Composite Index)는 어떻게 활용하는가?
1) 커버링 인덱스란?
별도로 클러스터링 인덱스를 통한 별도 조회 과정을 거치지 않고, 인덱스 테이블 내의 정보만으로도 원하는 정보들을 조회해올 수 있는 인덱스를 말한다.
CREATE INDEX idx_covering ON users (name, age);
SELECT name, age FROM users WHERE name = 'John';
데이터 테이블을 조회하지 않고, 인덱스에서 직접 데이터를 가져올 수 있음 → 속도 향상!
2) 복합 인덱스(Composite Index)
여러 개의 컬럼을 조합한 인덱스를 말한다.
CREATE INDEX idx_composite ON orders (user_id, created_at);
SELECT * FROM orders WHERE user_id = 1 AND created_at > '2024-01-01';
- user_id + created_at 두 개의 컬럼을 하나의 인덱스로 관리하여, 검색 속도가 향상된다.
인덱스를 너무 많이 사용하면 어떤 문제가 발생할 수 있는가?
1) 데이터 삽입/수정/삭제 성능 저하
- 인덱스가 많을수록, 데이터를 변경할 때마다 "모든 인덱스도 함께 갱신"해야 함 → 성능 저하!
2) 저장 공간 증가
- 인덱스는 별도의 공간을 차지하기 때문에, 너무 많으면 디스크 용량 증가
3) 쿼리 최적화 문제
- 너무 많은 인덱스가 있으면 MySQL이 "어떤 인덱스를 써야 할지 결정하기 어려움"
3. 트랜잭션과 동시성 제어
트랜잭션(Transaction)이란 무엇이며, ACID 특성은 각각 무엇을 의미하는가?
- 트랜잭션(Transaction)이란?
- 예시로 은행에서 A가 B에게 10만 원을 송금할 때, 1) A의 계좌에서 10만 원이 빠져나가고 2) B의 계좌에 10만 원이 입금되어야 한다.
- 그런데 만약 1번 과정만 수행되고 시스템이 다운된다면? 돈만 빠져나가고 입금되지 않는 심각한 문제가 발생된다.
- 그래서 데이터베이스에서는 "트랜잭션"을 사용하여, 모든 작업을 하나의 단위로 묶어 준다.
- 트랜잭션이란, 여러 개의 SQL 작업을 하나의 단위로 처리하는 것!
START TRANSACTION;
UPDATE accounts SET balance = balance - 100000 WHERE name = 'A';
UPDATE accounts SET balance = balance + 100000 WHERE name = 'B';
COMMIT; -- 모든 작업이 성공하면 저장
모두 성공하면 COMMIT(확정), 중간에 실패하면 ROLLBACK(되돌리기)한다.
- ACID (트랜잭션의 4원칙)
- A (원자성, Atomicity)
- 설명 : 모두 성공하거나, 모두 실패해야 하는 것을 말한다.
- 예시 : 돈을 이체할 때, A의 계좌에서 빠지기만 하면 안 되고 B의 계좌에도 들어와야 한다.
- C (일관성, Consistency)
- 설명 : 트랜잭션 실행 전과 후의 데이터 무결성이 유지되어야 한다.
- 예시 : 계좌 이체 후 전체 은행의 돈 총액은 변하면 안 된다.
- I (격리성, Isolation)
- 설명 : 여러 트랜잭션이 동시에 실행될 때 서로 영향을 주면 안 된다.
- 예시 : A가 돈을 보내는 동안 다른 사용자가 같은 데이터를 수정할 수 없어야 한다.
- D (지속성, Durability)
- 설명 : 트랜잭션이 완료되면 데이터는 영구적으로 저장되어야 한다.
- 예시 : 은행 시스템이 갑자기 꺼져도 돈이 전송된 기록은 유지되어야 함.
MySQL에서 트랜잭션을 지원하는 스토리지 엔진(InnoDB, MyISAM 등)의 차이점은?
- InnoDB의 특징 (트랜잭션 O)
- ACID 보장 (원자성, 일관성, 격리성, 지속성)
- MVCC 지원 → 동시성 처리 최적화
- 외래 키(Foreign Key) 지원
- MyISAM의 특징 (트랜잭션 X)
- 트랜잭션 지원 안 됨 → ROLLBACK 불가
- 빠른 읽기 성능 → 조회 속도가 빠름
- 충돌 방지 기능 부족 → 충돌 발생 시 데이터 손실 위험
트랜잭션 격리 수준(READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE)은 어떤 차이가 있는가?
트랜잭션 격리 수준에 따른 동시성 문제 제어 방법은 총 4가지가 있다.

- READ UNCOMMITTED (읽기 커밋되지 않음) : 트랜잭션이 아직 COMMIT되지 않은 데이터를 읽을 수 있음 (Dirty Read 발생!)
START TRANSACTION;
UPDATE accounts SET balance = 500 WHERE id = 1;
-- (다른 트랜잭션에서 아직 커밋되지 않은 값을 볼 수 있음)
ROLLBACK;
- READ COMMITTED (읽기 커밋됨) : 다른 트랜잭션이 COMMIT된 데이터만 읽을 수 있다. "Non-Repeatable Read"가 발생할 수 있다. 두 번 조회했을 때 값이 다를 수 있다.
SELECT balance FROM accounts WHERE id = 1;
-- (다른 트랜잭션에서 업데이트가 발생하면 값이 달라질 수 있음)
SELECT balance FROM accounts WHERE id = 1;
- REPEATABLE READ (반복 읽기, MySQL 기본값) : 같은 데이터를 여러 번 조회해도 값이 변하지 않는다. 하지만, "Phantom Read"가 발생할 수 있다. 읽은 값이 일관되지만, 새로운 행이 추가될 가능성 있다.
SELECT COUNT(*) FROM orders WHERE status = 'pending';
-- (다른 트랜잭션에서 새로운 주문이 추가되면 결과가 달라질 수 있음)
- SERIALIZABLE (직렬화) : 가장 강력한 격리 수준 → 동시 처리 성능이 떨어진다. 모든 트랜잭션이 순차적으로 실행된다. 가장 안전하지만, 가장 느리다는 단점이 있다.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
InnoDB의 MVCC(Multi-Version Concurrency Control)는 어떻게 동작하며, 어떤 장점이 있는가?
MVCC는 과거 버전을 유지하여 동시성을 높이는 기술이다. 이전 데이터(Undo Log)를 유지하여, 다른 트랜잭션이 과거 데이터를 볼 수 있도록 한다. 락(Lock)을 걸지 않고 데이터를 읽을 수 있어 성능이 향상된다.
SELECT balance FROM accounts WHERE id = 1;
-- (과거 데이터 스냅샷을 사용하여 빠르게 조회 가능!)
MVCC 덕분에 InnoDB는 동시성 처리가 뛰어나다. 트랜잭션이 많아도 성능이 저하되지 않는다.
Deadlock(교착 상태)은 어떻게 발생하며, 이를 방지하거나 해결하는 방법은?
Deadlock이란 두 개 이상의 트랜잭션이 서로 상대방이 가진 자원을 기다리면서 무한정 멈추는 상황을 말한다.
-- 트랜잭션 1
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- (여기서 멈춤)
-- 트랜잭션 2
START TRANSACTION;
UPDATE accounts SET balance = balance - 50 WHERE id = 2;
-- (서로 대기 상태 발생, DEADLOCK!)
- 해결 방법
- 트랜잭션의 실행 순서를 정해준다.
- 트랜잭션의 타임아웃을 설정한다.
- 결론
- Deadlock은 동시성 제어의 주요 문제이다.
- 트랜잭션 순서를 정하거나 타임아웃을 설정해서 해결 가능하다.
4. 조인(Join)과 쿼리 최적화
INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN의 차이점은?
- JOIN
두 개의 테이블을 연결해서 하나의 결과를 만드는 것이다. 예를 들어, students 테이블(학생)과 grades 테이블(성적)이 있다고 해보자.
| student_id | name |
|------------|-------|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
| student_id | score |
|------------|-------|
| 1 | 90 |
| 2 | 85 |
이제 학생과 성적을 함께 출력하려면 어떻게 해야 할까? JOIN을 사용해서 데이터를 연결 할 수 있다.
- INNERJOIN (교집합)
SELECT students.name, grades.score
FROM students
INNER JOIN grades ON students.student_id = grades.student_id;
| name | score |
|-------|-------|
| Alice | 90 |
| Bob | 85 |
INNER JOIN은 두 테이블에서 "일치하는 데이터만" 가져온다. Charlie는 성적 데이터가 없으므로 제외된다.
- LEFT JOIN (왼쪽 테이블 기준)
왼쪽 테이블의 모든 데이터를 가져오고, 오른쪽에 없는 데이터는 NULL로 표시.
SELECT students.name, grades.score
FROM students
LEFT JOIN grades ON students.student_id = grades.student_id;
아래처럼 성적 정보가 없는 Charlie도 포함된다. 단, NULL로 표시된다.
| name | score |
|---------|-------|
| Alice | 90 |
| Bob | 85 |
| Charlie | NULL |
- RIGHT JOIN (오른쪽 테이블 기준)
반대로 RIGHT JOIN은 오른쪽 테이블의 모든 데이터를 가져오고, 왼쪽에 없는 데이터는 NULL로 표시한다.
SELECT students.name, grades.score
FROM students
RIGHT JOIN grades ON students.student_id = grades.student_id;
RIGHT JOIN은 성적이 있는 학생들만 가져온다. Charlie는 성적이 없으므로 제외된다.
| name | score |
|-------|-------|
| Alice | 90 |
| Bob | 85 |
- FULL JOIN (합집합, MySQL은 지원 안 함)
두 테이블의 모든 데이터를 가져오고, 없는 부분은 NULL로 표시한다. MySQL에서는 FULL JOIN을 직접 지원하지 않으며, UNION을 사용해야 한다.
SELECT students.name, grades.score
FROM students
LEFT JOIN grades ON students.student_id = grades.student_id
UNION
SELECT students.name, grades.score
FROM students
RIGHT JOIN grades ON students.student_id = grades.student_id;
INNER JOIN + LEFT JOIN + RIGHT JOIN을 합친 형태이다.
| name | score |
|---------|-------|
| Alice | 90 |
| Bob | 85 |
| Charlie | NULL |
Nested Loop Join, Hash Join, Sort-Merge Join 등 MySQL의 조인 방식은 어떻게 동작하는가?
- Nested Loop Join (기본 방식)
두 테이블을 반복문으로 비교하면서 하나씩 매칭한다.
SELECT students.name, grades.score
FROM students
INNER JOIN grades ON students.student_id = grades.student_id;
아래처럼 중첩 반복문이 실행되는 구조이다.
for each row in students:
for each row in grades:
if students.student_id == grades.student_id:
출력
- Hash Join (MySQL 8.0 이상)
해시 테이블을 사용하여 빠르게 조인하는 방식이다.
SELECT * FROM A JOIN B ON A.id = B.id;
1. 작은 테이블을 해시 테이블로 변환
2. 큰 테이블을 스캔하며 해시 값을 비교하여 조인
- 장점
- 큰 테이블 조인에 유리
- O(n) 복잡도 (빠름)
- 단점 : 인덱스 없을 때만 사용됨
- Sort-Merge Join
두 테이블을 정렬한 후, 병합하면서 조인한다.
1. 두 테이블을 정렬
2. 정렬된 상태에서 병합
- 장점 : 정렬된 데이터에서는 효과적
- 단점 : 정렬 비용이 클 경우 비효율적
MySQL에서 서브쿼리보다 조인을 권장하는 이유는?
서브쿼리는 느리고, 조인이 더 빠르기 때문이다. 아래 쿼리로 예시를 살펴보자. 학생 한 명당 1번씩 서브쿼리가 실행됨 → O(n^2) 성능 문제 발생한다.
SELECT name, (SELECT score FROM grades WHERE grades.student_id = students.student_id) AS score
FROM students;
조인은 한 번에 데이터를 결합하므로 훨씬 빠르다. 따라서 서브쿼리는 작은 데이터에서만 사용하고, 큰 데이터에서는 조인이 훨씬 빠르다.
SELECT students.name, grades.score
FROM students
LEFT JOIN grades ON students.student_id = grades.student_id;
실행 계획(EXPLAIN)을 분석하는 방법과 주요 항목(EXPLAIN의 type, key, rows 등)은 무엇인가?
EXPLAIN은 MySQL이 쿼리를 어떻게 실행하는지 분석하는 도구이다.
EXPLAIN SELECT students.name, grades.score
FROM students
LEFT JOIN grades ON students.student_id = grades.student_id;
실행 계획 결과 예시는 아래와 같다.
| id | select_type | table | type | key | rows |
|----|------------|---------|-------|---------|------|
| 1 | SIMPLE | students | ALL | NULL | 1000 |
| 1 | SIMPLE | grades | ref | PRIMARY | 10 |
- type : ALL, INDEX, RANGE, REF, CONST, EQ_REF 등 (작을수록 좋음)
- key : 사용된 인덱스
- rows : 예상 조회 행 수 (작을수록 좋다)
EXPLAIN을 사용하여 성능 문제를 진단하고 최적화할 수 있다.
5. 저장 구조와 내부 동작 원리
MySQL의 데이터 파일과 로그 파일의 구조는 어떻게 구성되는가?
MySQL은 데이터를 저장하기 위해 여러 종류의 파일을 사용한다.
/var/lib/mysql/
├── my_database/
│ ├── my_table.ibd # InnoDB 테이블 데이터 파일
│ ├── my_table.frm # 테이블 정의 파일
│ ├── ibdata1 # 공통 테이블스페이스 (InnoDB)
│ ├── ib_logfile0 # Redo 로그 파일
│ ├── ib_logfile1 # Redo 로그 파일
│ ├── binlog.000001 # Binary 로그 파일
│ ├── relay-log.index # 복제 로그
│ ├── undo_001 # Undo 로그 파일
│ ├── mysql-bin.index # Binary 로그 인덱스
주요 파일은 아래와 같다.
- .ibd 파일 : InnoDB 테이블의 데이터와 인덱스를 저장
- .frm 파일 : 테이블의 구조(스키마) 정보를 저장 (MySQL 8.0부터 제거됨)
- ibdata1 : InnoDB의 공통 테이블스페이스 (모든 테이블의 데이터와 인덱스를 저장)
- ib_logfile0, ib_logfile1 : Redo 로그 파일 (데이터 복구 용도)
- binlog.000001 : Binary 로그 파일 (데이터 변경 사항 저장)
- undo_001 : Undo 로그 파일 (롤백을 위한 변경 사항 저장)
MySQL은 다양한 파일 시스템을 활용해 성능과 복구를 최적화한다.
MySQL의 Redo Log, Undo Log, Binary Log는 각각 어떤 역할을 하는가?
MySQL은 트랜잭션과 데이터 무결성을 보장하기 위해 3가지 주요 로그를 사용한다.
- Redo Log (재실행 로그)
전원이 나가도 데이터를 안전하게 복구하는 역할을 한다. ib_logfile0, ib_logfile1 파일에 저장된다.
InnoDB 트랜잭션이 COMMIT 되기 전에 변경 사항을 먼저 기록하여, 갑작스러운 종료에도 데이터를 복구 가능하다.
📂 Redo Log 동작 방식
1. 데이터 변경 발생 (UPDATE)
2. Redo Log에 먼저 기록
3. 일정 시간이 지나면 디스크에 실제 반영
- Undo Log (롤백 로그)
트랜잭션을 취소할 수 있도록 이전 데이터를 저장하는 역할을 담당한다.
undo_001 파일에 저장된다. ROLLBACK 실행 시 Undo Log를 사용해 이전 상태로 되돌릴 수 있다.
📂 Undo Log 동작 방식
1. UPDATE 실행 전, 변경 전 값을 Undo Log에 저장
2. 트랜잭션 중간에 오류 발생 → ROLLBACK 실행
3. Undo Log를 이용해 이전 데이터로 복구
- Binary Log (이진 로그)
MySQL 복제와 데이터 변경 사항을 기록하는 로그다. binlog.000001 파일에 저장된다. 데이터 변경(SQL 실행 기록)을 이진(Binary) 형태로 저장하여 장애 복구, 복제, Point-in-Time Recovery 가능하다.
📂 Binary Log 동작 방식
1. INSERT, UPDATE, DELETE 실행
2. Binary Log에 SQL 문장이 저장됨
3. 복제 서버에서 로그를 읽어와 동일한 변경을 수행
데이터가 실제로 디스크에 저장되는 방식과 버퍼 풀(Buffer Pool)의 역할은?
MySQL은 데이터를 메모리(Buffer Pool)에서 먼저 처리하고, 일정 시간 후 디스크에 저장한다.
- 데이터 저장 방식
📂 데이터 저장 과정
1. 클라이언트가 INSERT, UPDATE 실행
2. 변경 사항이 Buffer Pool(메모리)에 저장됨
3. 일정 시간이 지나면 데이터를 디스크에 기록 (Checkpoint)
📂 디스크 쓰기 방식
[ Buffer Pool ] → [ Redo Log ] → [ 디스크 저장 ]
- Buffer Pool (버퍼 풀)이란?
자주 사용하는 데이터를 메모리에 캐싱하여 속도를 높이는 공간이다.
- 데이터 페이지 캐싱 : 자주 사용하는 데이터를 RAM에 보관
- 쓰기 지연 (Delayed Write) : 디스크 쓰기를 최소화하여 성능 향상
- 동시성 향상 : 여러 트랜잭션을 빠르게 처리 가능
[ Buffer Pool ]
├── 데이터 페이지
├── 인덱스 페이지
├── 변경된 페이지 (Dirty Pages)
Auto Increment(자동 증가) 필드는 내부적으로 어떻게 동작하는가?
Auto Increment란 MySQL에서 기본 키(PK)를 자동으로 증가시키는 기능이다.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100)
);
- Auto Increment의 동작 방식
📂 Auto Increment 값 할당 과정
1. INSERT 실행 시 자동으로 ID 값 증가
2. 마지막 할당된 값은 테이블 메타데이터에 저장됨
3. MySQL이 AUTO_INCREMENT 값을 캐싱하여 속도를 최적화
📂 Auto Increment 값 저장 위치
[ InnoDB ]: 테이블의 메모리 내부 캐시 (재시작 시 초기화 가능)
[ MyISAM ]: .frm 파일에 저장 (재시작해도 유지됨)
6. MySQL 확장성과 분산 처리
샤딩(Sharding)과 파티셔닝(Partitioning)의 차이점은 무엇인가?
- 샤딩(Sharding)
하나의 데이터를 여러 개의 데이터베이스 서버로 나누어 저장하는 것이다.
- 데이터를 서버 단위로 분리한다.
- 각 샤드는 독립적인 데이터베이스 인스턴스이다.
📂 샤딩 예제 (사용자 데이터를 ID로 나누기)
Shard 1 (서버 A) → 1~10,000번 사용자 저장
Shard 2 (서버 B) → 10,001~20,000번 사용자 저장
Shard 3 (서버 C) → 20,001~30,000번 사용자 저장
샤딩 후에는 하나의 서버가 모든 데이터를 저장하지 않아도 된다.
- 파티셔닝(Partitioning)
하나의 테이블을 여러 개의 파티션으로 나누어 저장하는 것이다.
- 데이터를 테이블 단위로 나눔
- 하나의 데이터베이스 내에서 논리적으로 테이블을 분리
📂 파티셔닝 예제 (날짜별 데이터 분리)
orders 테이블
├── Partition 1 (2023년 데이터)
├── Partition 2 (2024년 데이터)
├── Partition 3 (2025년 데이터)
큰 테이블을 나누어 저장하여 조회 속도를 최적화할 수 있다.
- 샤딩 vs 파티셔닝 비교

- 샤딩 → 수평 확장 (서버를 추가)
- 파티셔닝 → 단일 서버 내에서 최적화
MySQL 복제(Replication) 방식(Semi-Synchronous, Asynchronous, GTID 등)의 차이점은?
- MySQL 복제(Replication)란?
하나의 데이터베이스(Primary)에서 다른 데이터베이스(Replica)로 데이터를 복제하는 것이다.
📂 MySQL 복제 기본 구조
[ Primary 서버 ] → [ Replica 1 ] → [ Replica 2 ]
1) 비동기 복제(Asynchronous Replication)
- Primary 서버가 데이터를 기록한 후, Replica로 전송하지만 기다리지 않는다.
- 빠르지만, 데이터 유실 가능
- Replica 서버가 데이터를 놓칠 수 있다.
2) 반동기 복제(Semi-Synchronous Replication)
- Primary 서버가 최소한 하나의 Replica 서버가 데이터를 받을 때까지 기다린다.
- 안전하지만 약간 느림
- 데이터 유실 가능성이 줄어듦
📂 반동기 복제 흐름
Primary 서버: INSERT INTO users VALUES (1, 'Alice');
Replica 1 서버: OK (확인 응답)
Primary 서버: COMMIT;
3) GTID 기반 복제(Global Transaction ID)
- 각 트랜잭션에 고유한 ID를 부여하여 복제를 추적한다.
- 복제 충돌 방지
- Replica 서버 변경이 용이
MySQL에서 Read Replica를 활용하는 방법과 한계점은?
- Read Replica 란
읽기 작업을 Replica 서버에서 처리하여 Primary 서버의 부하를 줄이는 기술
📂 Read Replica 구조
[ Primary 서버 (쓰기 전용) ] → [ Replica 1 (읽기 전용) ]
→ [ Replica 2 (읽기 전용) ]
- Read Replica 활용 방법
- 읽기 부하 분산
- SELECT 쿼리를 Replica에서 실행하여 성능 향상
- 백업 및 데이터 분석
- 백업을 위해 Replica를 활용
- 장애 복구(Failover)
- Primary 서버 장애 발생 시 Replica를 Primary로 승격
- 한계점
- 실시간 동기화가 안됨 (Replication Lag 발생)
- 쓰기(INSERT, UPDATE)는 Primary 서버에서만 가능
- 트랜잭션 일관성이 보장되지 않음
MySQL Cluster와 Galera Cluster는 어떤 원리로 다중 노드 환경을 구성하는가?
- MySQL Cluster란?
여러 개의 MySQL 노드를 묶어 하나의 대형 클러스터처럼 동작하게 만드는 기술이다.
📂 MySQL Cluster 구조
[ SQL 노드 1 ] - [ 데이터 노드 1 ]
[ SQL 노드 2 ] - [ 데이터 노드 2 ]
- 장점
- 데이터 자동 분산 저장
- 빠른 읽기/쓰기 처리
- 단점
- 복잡한 설정 필요
- 메모리 사용량이 많음
- Galera Cluster란?
모든 노드가 동일한 데이터를 가지는 동기 복제 클러스터이다. 기본적으로 MySQL은 한 개의 Primary(쓰기 전용)와 여러 개의 Replica(읽기 전용) 구조로 작동하지만 MySQL Group Replication, Galera Cluster, Percona XtraDB Cluster 같은 솔루션을 사용하면 멀티마스터 복제가 가능하다.
📂 Galera Cluster 구조
[ 노드 1 ] ⇄ [ 노드 2 ] ⇄ [ 노드 3 ]
- 장점
- 자동 장애 복구 가능
- 모든 노드에서 읽기/쓰기 가능
- 단점
- 네트워크 속도가 중요
- 트랜잭션 성능이 낮아질 수 있음
7. MySQL 운영 및 유지보수
데이터베이스 백업과 복구 전략(물리적 백업 vs 논리적 백업, Point-in-Time Recovery)은 어떻게 구성해야 하는가?
- 데이터베이스 백업이 왜 중요할까?
백업을 안 하면 데이터가 날아갈 수도 있다.
- 갑자기 서버가 다운되거나, 실수로 데이터를 삭제하면 어떻게 될까
- 백업이 없으면 데이터를 복구할 방법이 없다.
- 그래서 데이터베이스에서는 백업 전략을 미리 준비해야 한다.
- 백업의 두 가지 방식
MySQL에서 백업을 수행하는 두 가지 방식이 있다.
- 물리적 백업(Physical Backup)
- 논리적 백업(Logical Backup)
데이터베이스 테이블 설계 시 정규화(Normalization)와 반정규화(Denormalization)의 트레이드오프는?
MySQL에서 대량 데이터를 삽입/삭제할 때 주의할 점은?
주기적인 테이블 분석(ANALYZE TABLE)과 최적화(OPTIMIZE TABLE)의 역할은?
'DB' 카테고리의 다른 글
7가지 핵심 질문으로 알아보는 개발자를 위한 Redis 활용법 (0) | 2025.03.14 |
---|---|
윈도우함수(Window Function)로 중복 닉네임 처리하기 (1) | 2024.09.27 |
댓글