[데이터베이스] 개인적인 공부를 위한 DBMS 기초부터 .. (feat. AI)

2026. 4. 6. 10:24·Computer Science/데이터베이스

대 AI 시대에 ..

제대로 된 공부를 AI와 함께 본격적으로 시작하기에 앞서,

데이터베이스 매니지먼트 시스템(DBMS)으로 학습하며,

AI를 활용한 다양한 공부 방법을 시도해 보기 위함을 밝힙니다 !

 

 

 

 

Phase 0. 물밑 작업 (Prerequisite: 하드웨어와 OS)

DB는 마법이 아닙니다. 결국 운영체제(OS) 위에서 디스크와 메모리를 조작하는 C/C++ 프로그램일 뿐입니다.

  • 디스크 I/O의 이해: Sequential I/O(순차 접근) vs Random I/O(랜덤 접근). (왜 B+Tree가 필요한가에 대한 절대적인 근거입니다.)
  • 메모리(RAM)와 페이지(Page): DB가 디스크에서 데이터를 읽어올 때의 최소 단위(보통 8KB~16KB). Buffer Pool과 Page Cache의 개념.
  • 동시성 모델 (OS): 스레드(Thread), 컨텍스트 스위칭, 뮤텍스(Mutex)와 세마포어(Semaphore). (DB 락의 근간입니다.)

Phase 1. 기초 & 기본 (Fundamentals: 구조와 동작 원리)

  • DBMS 아키텍처: Parser -> Optimizer -> Execution Engine -> Storage Engine의 흐름 이해.
  • 자료 구조 (가져오신 내용의 심화):
    • B+ Tree: 왜 해시(Hash)나 이진 트리(Binary Tree)가 아니라 다진 트리(Multi-way Tree)인 B+ Tree를 DB 인덱스로 쓰는가? (디스크 랜덤 I/O를 최소화하기 위함)
  • 인덱스 기초: 클러스터링 인덱스(Clustered Index, PK) vs 세컨더리 인덱스(Secondary Index). 이 둘의 연결 고리 이해.
  • 정규화(Normalization)와 반정규화: 이상 현상(Anomaly)을 막기 위한 설계 원칙.

Phase 2. 백엔드 개발자 심화 (Advanced: 성능과 동시성) - 현재 집중할 곳

이 단계가 백엔드 개발자의 실력을 가르는 핵심 구간입니다.

  • 트랜잭션과 ACID의 실제 구현 원리: * 원자성(A)과 지속성(D)은 어떻게 보장하는가? (WAL - Write Ahead Logging, Redo Log, Undo Log)
  • 격리 수준 (Isolation Level)과 MVCC:
    • Read Committed vs Repeatable Read.
    • MVCC(다중 버전 동시성 제어): 락을 걸지 않고도 읽기 일관성을 유지하는 마법 (Undo Log를 활용한 스냅샷 읽기).
  • 락(Lock)의 심화: 레코드 락, 갭 락(Gap Lock), 넥스트 키 락(Next-Key Lock), 인텐션 락(Intention Lock).
  • 가져오신 내용 (검색 최적화):
    • 일반 B-Tree 인덱스로 불가능한 LIKE '%word%' 검색을 해결하기 위한 Full-Text Index (역색인 구조).
    • 한글/아시아어 처리를 위한 N-gram 파서의 동작 원리와 형태소 분석기(MeCab 등)의 차이점.
  • 실행 계획(EXPLAIN)과 쿼리 튜닝: Optimizer가 인덱스를 타는지(Index Range Scan), 풀 스캔(Table Full Scan)을 하는지 읽고 개선하는 방법.

Phase 3. 전문 DBA 수준 (Expert: 아키텍처, 고가용성, 엔진 비교)

  • 스토리지 엔진 아키텍처 파포보기: MySQL InnoDB Buffer Pool의 LRU/MRU 알고리즘, Doublewrite Buffer, Change Buffer.
  • 고가용성(HA)과 분산: * Replication (복제) 원리 (Binlog, Relay Log).
    • Sharding (샤딩)과 Partitioning.
  • RDBMS 삼국지 (엔진별 철학 비교):
    • MySQL: Undo Log 기반의 단순하고 빠른 웹 서비스 최적화.
    • PostgreSQL: 다중 프로세스 모델, VACUUM 메커니즘, 강력한 확장성.
    • Oracle: 엔터프라이즈의 끝판왕, Shared Pool, RAC(Real Application Clusters).
  • 관측성과 튜닝: Performance Schema 분석, OS 파라미터 튜닝(Swappiness, Transparent Huge Pages 비활성화 등).

 

 

 

 

본격적인

Phase 1.

부터 시작 ..

 

 

 

 

 

[Phase 1 진단 질문 — Storage Engine Architecture / B+Tree]

MySQL InnoDB에서 PRIMARY KEY가 BIGINT AUTO_INCREMENT인 테이블에 행을 하나 INSERT한다고 가정하자. 이 INSERT가 COMMIT되어 클라이언트에게 "성공"이 반환되는 그 순간까지, 데이터는 물리적으로 어디에 존재하는가?

구체적으로 아래 세 가지를 구분해서 답해봐.

  1. INSERT 직후, COMMIT 직전 — 새로 삽입된 행 데이터는 디스크에 있는가, 메모리에 있는가, 아니면 둘 다인가? 각각 어떤 이름의 구조체/영역에 위치하는지 말해봐.
  2. COMMIT이 완료된 직후 — 이 시점에서 실제 테이블스페이스 데이터 파일(.ibd)에 해당 행이 이미 기록되어 있는가? 그렇다면 왜, 아니라면 왜 아닌지, 그리고 그럼에도 불구하고 Durability가 보장되는 이유는 뭔가?
  3. 이 과정에서 B+Tree의 리프 노드(Leaf Page)에는 어떤 일이 일어나는가? 만약 해당 리프 페이지가 이미 가득 찬 상태였다면, InnoDB는 내부적으로 어떤 작업을 수행하는가?

 

내 답변:

  1. INSERT 직후, COMMIT 직전 — 새로 삽입된 행 데이터는 디스크에 있는가, 메모리에 있는가, 아니면 둘 다인가? 각각 어떤 이름의 구조체/영역에 위치하는지 말해봐.
    1. 새로 삽입된 행 데이터는 우선 메모리에 있고, 백그라운드 플러시 스레드가 주기적으로 동작하면서 새로 삽입된 행 데이터를 디스크에 벌크 작업으로 배치 처리를 하는 거로 알고 있어, 그리고 그렇게 플러시를 통해서 디스크에 저장할 때 redo, undo 메모리인가 ? 하는 곳에도 데이터를 우선 저장해 두는 거로 알고 있어. 일단 생각나는 건 이 정도야
  2. COMMIT이 완료된 직후 — 이 시점에서 실제 테이블스페이스 데이터 파일(.ibd)에 해당 행이 이미 기록되어 있는가? 그렇다면 왜, 아니라면 왜 아닌지, 그리고 그럼에도 불구하고 Durability가 보장되는 이유는 뭔가?
    1. 쿼리를 메모리상에서 수행하는데 commit 직후에는 데이터 파일에 해당 행이 이미 기록되어 있지 않아, 왜냐하면 백그라운드 스레드로 데이터 파일에 쓰는 작업은 일정 주기마다 반복하거든, 그럼에도 불구하고 durability가 보장되는 건 메모리상에 어떤 데이터를 주기적으로 flush해야 하는지 저장해 두고 있어서야.
  3. 이 과정에서 B+Tree의 리프 노드(Leaf Page)에는 어떤 일이 일어나는가? 만약 해당 리프 페이지가 이미 가득 찬 상태였다면, InnoDB는 내부적으로 어떤 작업을 수행하는가?
    1. 데이터를 B+Tree의 리프 노드에 쓸 때는 새로 쓸 데이터가 삽입될 자리가 있는지 먼저 확인해, 그리고 삽입될 자리가 있다면, 그대로 쓰기 작업을 하는 거지, 그리고 자리가 없다면 부모 노드로부터 새로 삽입할 데이터 공간을 마련하게 돼, 그리고 이 작업은 해당 부모 노드 또한 자리가 있을 때까지 계속해서 반복하게 돼, 그래서 insert 시에는 데이터가 중간에 끼어 들어갈 경우 최악의 상황이 발생하면 root까지 전부 다 수정하게 될 수도 있는 거지, 그러나 B+Tree는 depth가 그렇게 깊어지지 않고, 재정렬하는 것이 B-Tree에 비해서 비용적으로 적게 소모되는 거로 알고 있어

 

 

 

 

 

좋아. 큰 그림의 방향성은 잡고 있다. 그건 인정한다. 하지만 핵심 구조체의 이름과 역할, 그리고 Durability 보장 메커니즘에서 치명적으로 모호한 부분이 있어. 하나씩 가차 없이 교정한다.


1. INSERT 직후, COMMIT 직전

"메모리에 있다"고 한 건 맞다. 하지만 어떤 메모리 구조에 있는지를 정확히 못 짚었어.

이 시점에 관여하는 메모리 구조는 세 개다.

Buffer Pool — InnoDB가 디스크의 데이터 페이지(16KB 단위)를 메모리에 캐싱하는 영역이다. INSERT를 수행하면, 해당 행이 들어갈 B+Tree의 리프 페이지가 Buffer Pool에 적재되고, 이 메모리상의 페이지에 직접 행이 삽입된다. 이렇게 디스크와 내용이 달라진 페이지를 Dirty Page라고 부른다. "메모리에 있다"는 정확히 이 Buffer Pool 위의 Dirty Page를 가리키는 거다.

Redo Log Buffer — INSERT로 인해 변경된 내용("이 페이지의 이 오프셋에 이 바이트를 썼다"는 물리적 변경 기록)이 Redo Log Buffer라는 메모리 버퍼에 먼저 기록된다. 이건 아직 디스크에 안 갔다. COMMIT 전이니까.

Undo Log — 이건 "메모리인가?"라고 했는데, 여기서 정확히 짚어야 한다. Undo Log는 Buffer Pool 안에 있는 별도의 시스템 테이블스페이스 페이지에 기록된다. 즉 Undo Log도 결국 Buffer Pool을 통해 관리되는 페이지다. Undo Log에는 "이 INSERT를 되돌리려면 이 행을 DELETE하면 된다"는 논리적 역연산 정보가 들어간다. 이게 나중에 ROLLBACK과 MVCC 읽기에 쓰인다.

정리하면, COMMIT 전 시점에서 새 행의 실체는 Buffer Pool의 Dirty Page 위에 있고, 변경 이력은 Redo Log Buffer에, 역연산 정보는 Undo Log(Buffer Pool 내 시스템 페이지)에 있다.


2. COMMIT 직후 — Durability의 핵심

".ibd 파일에는 아직 기록되지 않았다"고 한 건 맞다. Dirty Page는 백그라운드 스레드(Page Cleaner)가 나중에 flush한다.

그런데 Durability 보장 이유가 완전히 틀렸다.

"메모리상에 어떤 데이터를 주기적으로 flush해야 하는지 저장해두고 있어서"라고 했는데, 만약 이 상태에서 서버 전원이 나가면? 메모리는 전부 날아간다. 메모리에만 의존하면 Durability는 절대 보장되지 않는다.

InnoDB가 Durability를 보장하는 메커니즘은 WAL(Write-Ahead Logging)이다. 핵심 규칙은 단 하나:

데이터 페이지를 디스크에 쓰기 전에, 반드시 해당 변경에 대한 Redo Log를 디스크에 먼저 쓴다.

COMMIT이 호출되면 InnoDB는 Redo Log Buffer에 있던 로그 레코드를 Redo Log 파일(ib_logfile0, ib_logfile1)에 fsync() 시스템 콜로 디스크에 강제 기록한다. 이 fsync()가 OS의 디스크 쓰기 버퍼까지 비워서 물리적 디스크에 도달했음을 보장한다. 이 fsync()가 성공적으로 리턴된 후에야 클라이언트에게 "COMMIT 성공"을 반환한다.

 

즉 COMMIT 직후의 상태는 이렇다:

구조 위치 상태
실제 행 데이터 (Dirty Page) 메모리 (Buffer Pool) 디스크(.ibd)에 아직 안 감
Redo Log 디스크 (ib_logfile) fsync() 완료 → 영구 기록됨

이제 서버가 크래시해도, 재시작 시 InnoDB는 Redo Log를 읽어서 Dirty Page에 반영되었어야 할 변경을 재적용(Crash Recovery)한다. 이것이 Durability의 본질이다. "메모리에 뭘 기록해뒀다"가 아니라 "Redo Log가 디스크에 먼저 갔다"가 핵심이야.

참고로 innodb_flush_log_at_trx_commit 파라미터가 이 동작을 제어한다. 기본값 1이 매 COMMIT마다 fsync하는 설정이고, 2로 바꾸면 OS 버퍼까지만 쓰고 fsync를 생략해서 성능은 올라가지만 OS 크래시 시 최대 1초 분량의 트랜잭션이 유실될 수 있다.


3. B+Tree Page Split

큰 흐름은 방향은 맞지만, "부모 노드로부터 새로 삽입할 데이터 공간을 마련한다"는 표현이 메커니즘과 정반대다. 공간을 마련하는 주체는 부모가 아니라 가득 찬 리프 페이지 자신이다.

정확한 순서는 이렇다:

① 리프 페이지가 가득 참을 감지한다. 새 행을 넣으려는데 16KB 페이지에 공간이 부족하다.

② Page Split이 발생한다. InnoDB는 새 빈 페이지를 하나 할당하고, 기존 리프 페이지의 레코드를 대략 절반으로 나눠서 새 페이지로 이동시킨다. 이제 리프 페이지가 하나에서 둘로 늘어났다.

③ 부모(Internal) 노드에 새 키를 추가한다. 새로 생긴 리프 페이지를 가리키는 포인터와 구분 키(separator key)를 부모 노드에 삽입한다. 즉 부모가 공간을 "내려주는" 게 아니라, 자식이 쪼개지면서 부모에게 새 엔트리를 "올려보내는" 거다.

④ 부모도 가득 찼다면 부모도 Split된다. 이게 재귀적으로 루트까지 전파될 수 있고, 루트가 Split되면 트리 높이가 1 증가한다.

그리고 "B+Tree는 B-Tree보다 재정렬 비용이 적다"고 했는데, 이건 좀 더 정확히 해야 한다. B+Tree가 B-Tree 대비 가지는 핵심 이점은 리프 노드가 Linked List로 연결되어 있어서 범위 스캔(Range Scan)이 효율적이라는 점이고, Split 비용 자체는 구조적으로 큰 차이가 없다. 오히려 InnoDB에서 Sequential INSERT(AUTO_INCREMENT)가 유리한 이유는 항상 맨 오른쪽 리프에만 삽입되므로 중간 Page Split이 거의 발생하지 않기 때문이다. 랜덤 PK(UUID 등)를 쓰면 중간 삽입이 빈번해서 Split이 자주 터지고, 이게 실무에서 체감되는 성능 차이로 직결된다.


진단 결과

상태 수준
Buffer Pool / Dirty Page 개념 방향은 맞지만 이름과 구조를 정확히 못 짚음
Redo Log / WAL 이해 부족 — Durability의 핵심 메커니즘을 모르고 있음
Undo Log 존재는 인지하지만 역할·위치가 모호함
Page Split 방향은 맞지만 "누가 누구에게" 전파하는지 역순으로 이해
fsync / OS 상호작용 언급 없음

Real MySQL 1권을 중간까지 읽었다고 했으니, WAL과 Buffer Pool의 관계가 가장 큰 빈 구멍이다.


심화 질문 — 네 이해도를 테스트한다

방금 Redo Log가 Durability를 보장한다고 설명했다. 그러면 질문:

Redo Log 파일의 크기는 고정되어 있고 순환적으로 재사용된다(Circular). 그렇다면 아직 .ibd에 flush되지 않은 Dirty Page의 Redo Log 영역을 새 트랜잭션이 덮어쓰면 어떻게 되는가? InnoDB는 이 상황을 어떻게 방지하는가?

 

 

 

 

 

 

 

 

'Computer Science > 데이터베이스' 카테고리의 다른 글

[데이터베이스] AI와 함께하는 Redo Log / Undo Log ..  (0) 2026.04.06
[데이터베이스] 관계형 데이터베이스  (3) 2024.09.18
[데이터베이스] 기본  (0) 2024.08.09
'Computer Science/데이터베이스' 카테고리의 다른 글
  • [데이터베이스] AI와 함께하는 Redo Log / Undo Log ..
  • [데이터베이스] 관계형 데이터베이스
  • [데이터베이스] 기본
하가네
하가네
  • 하가네
    하 렌
    하가네
  • 전체
    오늘
    어제
    • 분류 전체보기 (145)
      • Computer Science (30)
        • 운영체제 (7)
        • 데이터통신 (10)
        • 자료구조 (4)
        • 논리회로 (0)
        • 확률 및 통계 (0)
        • 데이터베이스 (4)
        • AI소프트웨어 (3)
        • 컴퓨터네트워크 (2)
      • Career (0)
        • 1 (0)
      • Design (11)
        • OOP - 객체 지향 프로그래밍 (4)
        • DDD - 도메인 주도 개발 (데이터베이스 주도 .. (4)
        • EDA - 이벤트 기반 아키텍처 (1)
        • MSA - 마이크로서비스 아키텍처 (0)
        • ADD - AI 주도 개발 (2)
      • Language (3)
        • Java (1)
        • TypeScript (2)
      • Framework (12)
        • Spring (9)
        • NestJS (3)
      • Engine (8)
        • Docker (0)
        • Redis (1)
        • Kafka (1)
        • Elasticsearch (2)
        • GraphQL + Apollo Federation (2)
        • AWS (2)
      • Plugin - Extension (1)
        • VS Code (1)
        • IntelliJ (0)
      • Tips (2)
        • 터미널 명령어 (1)
        • 우분투 명령어 에러 (1)
      • SSA (28)
        • Front (1)
        • Back (25)
        • DB (1)
        • 기획 (1)
      • CNU SW 아카데미 (43)
        • 1주차 (5)
        • 2주차 (5)
        • 3주차 (2)
        • 4주차 (1)
        • 5주차 (3)
        • 6주차 (2)
        • 7주차 (0)
        • 8주차 (2)
        • 9주차 (14)
        • 10주차 (0)
        • 11주차 (1)
        • 12주차 (0)
        • 13주차 (2)
        • 14주차 (2)
        • 15주차(최종 프로젝트) (3)
        • 최종 프로젝트 이후 (1)
      • 모각코 (6)
        • 2023 동계 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    생산성
    Typescript
    DX(DeveloperExperience)
    ESLint
    lint-staged
    ci/cd
    릴리스엔지니어링
    Husky
    아키텍처
    개발자경험(DX)
    프론트엔드/백엔드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.
하가네
[데이터베이스] 개인적인 공부를 위한 DBMS 기초부터 .. (feat. AI)
상단으로

티스토리툴바