데이터베이스 관리 시스템
고친 사람 github-actions[bot]
데이터베이스 관리 시스템은 데이터를 대신 맡아 두었다가 꺼내 주는 프로그램입니다. 애플리케이션은 파일을 직접 열지 않고 이 프로그램에 필요한 것을 요청합니다. 여럿이 한꺼번에 써도 데이터가 엉키지 않게 지키는 일도 이 프로그램이 맡습니다.
쉽고 빠른 이해
DBMS(Database Management System, 데이터베이스 관리 시스템)는 데이터를 맡아 두었다가 요청이 오면 찾아 주고 고쳐 주는 프로그램입니다. 쇼핑몰 서버가 「회원 7번의 주문 목록」을 달라고 하면 DBMS 가 찾아서 돌려줍니다.
이게 없으면 애플리케이션(데이터를 쓰는 쪽 프로그램)마다 자기 파일을 따로 들고 직접 읽고 씁니다. 같은 정보가 여러 벌로 갈려 어긋납니다. 둘이 동시에 쓰면 한쪽 내용이 사라집니다. 쓰는 도중에 전원이 꺼지면 반쯤 고친 채로 남습니다.
이렇게 돕니다:
- 애플리케이션이 원하는 것을 정해진 말로 적어 보냅니다
- DBMS 가 어떻게 찾을지 스스로 정하고 데이터를 꺼내 돌려줍니다
- 고치는 요청이면 무엇을 고칠지 기록부터 남기고 고칩니다
애플리케이션 하나만 읽는 설정 파일처럼 함께 고칠 일이 없는 데이터라면 파일로 충분합니다.
대가는 따로 띄우고 돌봐야 하는 DBMS 가 하나 늘어난다는 것입니다. 모든 요청이 DBMS 를 거치므로, DBMS 가 멈추면 이를 쓰는 서비스도 같이 멈춥니다.
상세
은행 창구를 떠올리면 됩니다. 손님은 금고에 직접 들어가지 않습니다. 창구 직원에게 잔고를 묻거나 돈을 보내 달라고 말할 뿐입니다. 금고를 여닫고 장부를 고치는 일은 직원이 맡습니다.
데이터베이스 관리 시스템(Database Management System, DBMS)은 데이터베이스를 만들고, 그 안의 데이터를 넣고 꺼내고 고치는 일을 도맡는 소프트웨어입니다. 데이터를 쓰는 쪽인 애플리케이션은 데이터가 담긴 파일을 직접 열지 않습니다. 원하는 것을 DBMS 에 요청하면 DBMS 가 파일을 읽어 결과를 돌려줍니다.
쇼핑몰 서버를 예로 들면 이렇습니다. 서버가 「회원 7번의 주문 목록」을 달라고 요청합니다. DBMS 는 디스크에서 그 주문들을 찾아 표 모양으로 돌려줍니다. 서버 코드는 주문이 어느 파일 어디에 적혀 있는지 모릅니다.
데이터베이스와 DBMS 는 다른 것을 가리킵니다. 데이터베이스는 담긴 데이터입니다. DBMS 는 그 데이터를 담고 다루는 프로그램입니다.
일상에서는 둘 다 흔히 DB(DataBase, 데이터베이스)라고 줄여 부릅니다. 「DB 서버를 띄운다」의 DB 는 프로그램이고, 「DB 를 옮긴다」의 DB 는 담긴 데이터입니다.
파일을 직접 다룰 때 생기는 곤란
DBMS 가 왜 따로 있는지는 DBMS 없이 일하던 방식과 견주면 보입니다. 애플리케이션마다 자기 데이터를 자기 파일에 직접 적고 읽는 방식입니다. 이 방식을 파일 처리 시스템이라고 부릅니다.
데이터가 커지고 같은 데이터를 쓰는 애플리케이션이 늘면 이 방식에서 곤란이 넷 생깁니다.
| 곤란 | 벌어지는 일 |
|---|---|
| 같은 데이터가 여러 벌 | 주문 애플리케이션과 배송 애플리케이션이 고객 주소를 따로 들고 있다. 한쪽만 고치면 둘이 어긋난다 |
| 파일 모양이 코드에 박힘 | 칸 하나를 더하면 그 파일을 읽는 애플리케이션을 전부 고쳐야 한다 |
| 동시에 쓰면 덮어씀 | 두 애플리케이션이 같은 줄을 읽고 각자 고쳐 쓰면 먼저 쓴 쪽의 내용이 사라진다 |
| 중간에 멈추면 반쪽 | 계좌 이체에서 돈을 뺀 뒤 넣기 전에 전원이 꺼지면 돈이 사라진 채로 남는다 |
넷 모두 애플리케이션 하나하나가 알아서 풀기 어렵습니다. 그래서 데이터를 다루는 일을 애플리케이션들에서 걷어 내 한 곳에 모았습니다. 그 한 곳이 DBMS 입니다.
DBMS 가 맡는 일
이 소절은 DBMS 가 하는 일을 여섯 가지로 나눠 봅니다. 앞의 곤란 넷이 각각 어느 일로 풀리는지는 소절 끝의 표에 모았습니다.
데이터의 모양을 정합니다. 데이터를 넣기 전에 어떤 표에 어떤 칸이 있고, 칸마다 어떤 값을 받는지 먼저 적어 둡니다. 이 설계도를 스키마라고 부릅니다. 스키마를 DBMS 가 쥐고 있어서, 애플리케이션은 파일 모양을 몰라도 칸 이름만으로 데이터를 다룹니다.
스키마 덕분에 칸이 하나 늘어도 그 칸을 안 쓰는 애플리케이션은 고칠 필요가 없습니다. 저장하는 방식이 바뀌어도 애플리케이션이 흔들리지 않는 이 성질을 데이터 독립성이라고 부릅니다.
원하는 것만 말하면 찾아 줍니다. 애플리케이션은 「어디서 어떻게 읽어라」가 아니라 「무엇을 달라」만 적어 보냅니다. 이렇게 요청을 적는 말을 질의 언어라고 부릅니다. 행(줄)과 열(칸)로 된 표에 담는 DBMS 는 SQL(Structured Query Language, 구조화 질의 언어)을 씁니다.
아래는 SQL 로 표를 만들고, 한 줄을 넣고, 다시 꺼내는 세 문장입니다.
CREATE TABLE users (id INT, name TEXT);
INSERT INTO users VALUES (7, '은수');
SELECT name FROM users WHERE id = 7; -- 은수
세 문장 어디에도 파일 이름이나 디스크 위치가 없습니다. 어디서 어떻게 읽을지는 DBMS 가 정합니다.
7번을 찾는 길은 둘입니다. 표를 처음부터 훑거나 인덱스로 바로 가는 것입니다. 인덱스는 책 뒤의 찾아보기처럼, 값으로 줄을 바로 찾게 해 주는 별도 목록입니다. 둘 가운데 무엇을 쓸지도 DBMS 가 고릅니다.
여럿이 동시에 써도 엉키지 않게 합니다. 같은 줄을 두 요청이 한꺼번에 고치려 하면 DBMS 가 둘을 갈라 놓습니다. 가장 쉬운 방법은 한쪽을 잠깐 기다리게 하는 것입니다. 이 방법이 락입니다.
기다리게만 하면 읽는 쪽도 고치는 쪽이 끝날 때까지 멈춥니다. 그래서 고치는 동안에도 읽는 쪽에는 고치기 전 모습(버전)을 따로 남겨 보여 주는 방법이 있습니다. 이 방법이 MVCC(Multi-Version Concurrency Control, 다중 버전 동시성 제어)입니다.
여러 요청을 한 덩어리로 묶습니다. 이체의 빼기와 넣기처럼 함께 되어야 하는 요청들을 트랜잭션 하나로 묶습니다. DBMS 는 트랜잭션 안의 일을 전부 반영하거나 하나도 반영하지 않습니다. 반쯤 된 상태는 다른 요청에 드러나지 않습니다.
멈췄다 다시 켜져도 되살립니다. DBMS 는 데이터를 고치기 전에, 무엇을 어떻게 고칠지 차례로 적어 두는 기록 파일에 먼저 적습니다. 이 기록 파일을 로그라고 부릅니다. 로그부터 쓰는 방식은 WAL(Write-Ahead Logging, 미리 쓰기 로그)이라고 부릅니다.
전원이 꺼졌다 켜지면 DBMS 는 로그를 읽습니다. 끝난 트랜잭션은 마저 반영합니다. 덜 끝난 트랜잭션의 고침은 데이터 파일에 이미 쓰여 있을 수도 있습니다. 그래서 로그를 보고 그 고침을 고치기 전으로 되돌립니다.
누가 무엇을 볼지 정합니다. 사용자마다 읽을 수 있는 표와 고칠 수 있는 표를 따로 정해 둡니다. 이 설정이 권한입니다. 파일을 직접 열던 방식에서는 파일을 열 수 있으면 안의 내용을 전부 볼 수 있었습니다.
앞의 곤란 넷과 짝지으면 이렇습니다.
| 곤란 | DBMS 가 맡는 일 |
|---|---|
| 같은 데이터가 여러 벌 | 데이터를 한 곳에 두고 모든 애플리케이션이 그곳에 요청한다 |
| 파일 모양이 코드에 박힘 | 스키마를 DBMS 가 쥐고 애플리케이션은 칸 이름만 쓴다 |
| 동시에 쓰면 덮어씀 | 락이나 MVCC 로 동시 요청을 갈라 놓는다 |
| 중간에 멈추면 반쪽 | 트랜잭션으로 묶고 로그로 되살린다 |
권한은 곤란 넷과 별개로 붙은 일입니다. 한 데이터를 여러 사람과 애플리케이션이 나눠 쓰게 되면서 생겼습니다.
요청 하나가 DBMS 안을 지나가는 길
DBMS 안은 크게 세 덩어리로 나뉩니다. 앞에서 본 SELECT name FROM users WHERE id = 7 한 줄은 질의 처리기 → 트랜잭션 관리자 → 저장 관리자를 차례로 지나갑니다. 이 한 줄을 따라가며 세 덩어리를 봅니다.
첫 덩어리는 질의 처리기입니다. 받은 문장을 읽어 뜻을 풉니다. 위 문장이라면 「users 표에서 id 가 7 인 줄의 name 을 달라」는 뜻이 됩니다.
뜻을 풀었으면 데이터를 어떤 순서로 어떻게 찾을지 계획을 세웁니다. 이 계획을 실행 계획이라고 부릅니다.
7번을 찾는 계획은 여럿일 수 있습니다. 표를 처음부터 훑는 계획과 인덱스로 바로 가는 계획이 그 예입니다. 이 가운데 비용이 적게 드는 쪽을 고르는 부품이 질의 옵티마이저입니다.
둘째 덩어리는 트랜잭션 관리자입니다. 누가 7번 줄을 고치는 중이면 락이나 MVCC 로 두 요청을 갈라 놓습니다. 고치는 요청이 지나갈 때는 로그를 써서 멈췄을 때 되살릴 준비도 합니다.
셋째 덩어리는 저장 관리자입니다. 7번 줄을 실제로 꺼내 오는 일을 맡습니다. 그런데 디스크는 메모리보다 훨씬 느립니다.
그래서 저장 관리자는 자주 읽는 데이터를 메모리에 올려 둡니다. 이 메모리 구역을 버퍼 풀이라고 부릅니다. 7번 줄이 버퍼 풀에 있으면 디스크에 가지 않고 바로 돌려줍니다. 버퍼 풀에 없을 때만 디스크에서 읽어 옵니다.
flowchart TD
A["애플리케이션"] -->|SQL 문장| Q
subgraph D["DBMS"]
Q["질의 처리기 · 실행 계획을 고른다"] --> T["트랜잭션 관리자 · 락과 로그"]
T --> S["저장 관리자 · 버퍼 풀"]
end
S -->|읽을 때 버퍼 풀에 없으면| F["디스크"]
그림에서 볼 것은 애플리케이션이 디스크에 닿지 않는다는 점입니다. 디스크까지 가는 길은 전부 DBMS 안에 있습니다.
고치는 요청은 길이 하나 더 있습니다. DBMS 는 대개 로그를 디스크에 쓴 뒤에 「끝났다」고 답합니다. 데이터 파일은 나중에 모아서 고칩니다.
sequenceDiagram
participant 애플리케이션
participant DBMS
participant 로그
participant 데이터 파일
애플리케이션->>DBMS: 7번의 이름을 바꿔라
DBMS->>로그: 바꿀 내용을 먼저 적는다
Note over DBMS: 버퍼 풀의 데이터를 고친다
DBMS-->>애플리케이션: 끝났다
DBMS->>데이터 파일: 나중에 모아서 고친다
데이터 파일에 아직 안 쓴 채로 전원이 꺼져도 잃는 것이 없습니다. 다시 켜지면 로그에 적힌 대로 마저 고치면 되기 때문입니다. 데이터 파일 쓰기를 미뤄 두면 고칠 때마다 디스크 여기저기를 오갈 필요가 줄어듭니다.
데이터를 담는 모양에 따른 갈래
DBMS 는 데이터를 어떤 모양으로 담느냐에 따라 갈래가 나뉩니다. 모양이 다르면 잘 푸는 요청도 달라집니다.
| 갈래 | 데이터를 담는 모양 | 잘 푸는 요청 |
|---|---|---|
| 관계형 | 행과 열로 된 표. 표끼리는 같은 값을 가진 칸으로 이어 붙인다 | 여러 표를 이어 붙여 조건에 맞는 줄 고르기 |
| 키-값 | 이름표 하나에 값 하나 | 이름표 하나로 값 하나 꺼내기 |
| 문서형 | 이름과 값을 겹겹이 적은 문서 한 덩이 | 한 덩이를 통째로 넣고 꺼내기 |
| 그래프형 | 점과 점 사이를 잇는 선 | 선을 따라 이웃의 이웃 찾기 |
| 계층형 | 부모 하나에 자식 여럿이 매달린 나무 | 부모에서 자식으로 내려가며 찾기 |
표의 다섯 가운데 백엔드에서 가장 흔히 만나는 것은 관계형입니다. 앞에서 본 SQL 이 관계형 DBMS 의 질의 언어입니다. 계층형은 관계형보다 먼저 나온 갈래입니다.
서버로 띄우나 애플리케이션 안에 넣나
같은 DBMS 라도 어떻게 돌리느냐에 따라 두 꼴로 나뉩니다. 이 소절은 DBMS 가 애플리케이션과 어떻게 붙는지를 봅니다.
첫째는 서버형입니다. DBMS 가 따로 떠 있는 프로세스입니다. 애플리케이션은 네트워크 너머로 접속해 요청을 보냅니다. 여러 애플리케이션이 한 DBMS 를 나눠 쓸 수 있습니다. PostgreSQL · MySQL · Oracle 이 이 꼴입니다.
서버형은 접속을 맺는 데 시간이 듭니다. 그래서 백엔드 서버는 접속을 미리 여러 개 맺어 두고 요청마다 돌려 씁니다. 이 묶음을 커넥션 풀이라고 부릅니다.
둘째는 임베디드형입니다. DBMS 가 애플리케이션 안에 부품으로 들어가, 같은 프로세스 안에서 파일 하나를 직접 다룹니다. 네트워크도 따로 띄울 서버도 없습니다. 폰 앱이나 데스크톱 앱이 자기 데이터를 담을 때 쓰는 SQLite 가 이 꼴입니다.
언제 쓰고 언제 안 쓰나
DBMS 가 값을 하는지는 데이터를 누가, 얼마나 오래, 어떻게 고치느냐로 갈립니다.
| 상황 | 생기는 곤란 | DBMS |
|---|---|---|
| 여러 애플리케이션이나 사용자가 같은 데이터를 함께 고친다 | 여러 벌 · 덮어씀 | 쓴다 |
| 데이터가 오래 남는 동안 칸이 늘고 쓰는 애플리케이션이 바뀐다 | 모양이 코드에 박힘 | 쓴다 |
| 여러 고침이 함께 되거나 함께 안 되어야 한다 | 반쪽 | 쓴다 |
| 애플리케이션 하나만 읽는 설정 파일 하나 | 없음 | 파일로 충분하다 |
| 한 번 적고 나면 읽기만 하는 작은 기록 | 없음 | 파일로 충분하다 |
위 셋은 앞에서 본 곤란 넷이 생기는 조건이고, 그 곤란을 DBMS 가 맡습니다. 아래 둘은 곤란이 생기지 않으니 DBMS 를 들일 이유가 없습니다.
들이면 대가가 따릅니다. 따로 띄우고 돌봐야 하는 DBMS 가 하나 늘어납니다. 데이터를 잃지 않게 백업을 챙겨야 합니다. DBMS 의 버전을 올리는 일과 접속 수를 관리하는 일도 붙습니다.
요청마다 할 일도 늘어납니다. 문장 읽기 · 계획 세우기 · 락 확인 · 로그 쓰기를 차례로 거칩니다. 파일 하나를 바로 읽는 것보다 단계가 많습니다.
모든 요청이 DBMS 를 거친다는 점도 대가입니다. DBMS 가 멈추면 이를 쓰는 서비스가 같이 멈춥니다. 이렇게 하나가 멈추면 전체가 멈추는 부품을 단일 장애점이라고 부릅니다.
이 곤란을 덜려고 DBMS 를 한 벌 더 띄워 두기도 합니다. 원래 DBMS 가 고친 내용을 그대로 따라 적게 해 두었다가, 원래 쪽이 멈추면 그쪽으로 넘어갑니다. 이 방식을 복제라고 부릅니다.
관련 항목
DBMS 가 담고 다루는 대상
데이터베이스 · 스키마 · 테이블 · 인덱스 · 뷰 · 카탈로그
DBMS 에 요청을 적는 질의 언어
SQL · 질의 언어 · DDL · DML · DCL
DBMS 안을 이루는 부품
질의 처리기 · 질의 옵티마이저 · 실행 계획 · 트랜잭션 관리자 · 저장 관리자 · 버퍼 풀 · 스토리지 엔진
DBMS 가 지키는 약속과 그 수단
트랜잭션 · ACID · 원자성 · 일관성 · 격리 수준 · 락 · MVCC · WAL · 체크포인트 · 참조 무결성 · 제약조건
데이터를 담는 모양으로 갈린 DBMS 갈래
관계형 데이터베이스 · 관계형 데이터베이스 관리 시스템 · NoSQL · 키-값 저장소 · 문서 데이터베이스 · 그래프 데이터베이스 · 계층형 데이터베이스 · 네트워크형 데이터베이스
DBMS 로 쓰이는 제품
Oracle · PostgreSQL · MySQL · SQLite · SQL Server · MongoDB · Redis
DBMS 가 나오기 전의 저장 방식과 그 곤란
파일 처리 시스템 · 파일 시스템 · 데이터 중복 · 갱신 손실 · 데이터 독립성
DBMS 를 굴리는 운영 업무
데이터베이스 관리자 · 백업과 복구 · 복제 · 샤딩 · 권한 · 접근 제어 · 단일 장애점
애플리케이션이 DBMS 에 접속할 때 쓰는 연결 도구
커넥션 풀 · JDBC · ODBC · ORM · 데이터베이스 드라이버
DBMS 가 받는 작업 부하의 종류
다른 이름: DBMS · Database Management System