ๆ่ฒ็ฎ็ใงไฝๆใใใใใฃในใฏใใผในใฎใใผใฟใใผในใจใณใธใณใไปฅไธใฎๆฉ่ฝใๅฎ่ฃ ใใฆใใพใ๏ผ
- ใใฃในใฏใใผในในใใฌใผใธ - ใใผใธๆง้ ใใใใใกใใผใซ๏ผLRU๏ผ
- WAL (Write-Ahead Logging) - ใฏใฉใใทใฅใชใซใใชใฎใใใฎใญใฐๅ ่กๆธใ่พผใฟ
- ARIES Recovery - 3ใใงใผใบใชใซใใช๏ผAnalysis โ Redo โ Undo๏ผ
- MVCC - ในใใใใทใงใใๅ้ขใซใใไธฆ่กๅถๅพก
- B-Treeใคใณใใใฏใน - ใซใฉใ ๅคใใผในใฎใญใผใ่ชๅใกใณใใใณในใSELECT WHEREๆ้ฉๅ
- SQLใใผใตใผ - CREATE, INSERT, SELECT, UPDATE, DELETE
- VACUUM - MVCCใใใใฟใใซใฎใฌใใผใธใณใฌใฏใทใงใณ
graph TD
subgraph REPL["REPL (cmd/minidb)"]
Main["main.go"]
end
subgraph Engine["Engine (engine.go)"]
E["Engine"]
end
subgraph SQL["SQL Layer"]
Lexer --> Parser --> Executor
end
subgraph Txn["Transaction Layer"]
TxnManager["TxnManager<br/>BEGIN / COMMIT / ROLLBACK"]
Snapshot["MVCC Snapshot<br/>Visibility Check"]
TxnManager --> Snapshot
end
subgraph Storage["Storage Layer"]
Catalog["Catalog<br/>Schema"]
TableHeap["TableHeap<br/>Rows"]
BTree["B-Tree Index"]
BufferPool["BufferPool<br/>LRU Cache"]
DiskManager["DiskManager<br/>Page I/O"]
Catalog --> BufferPool
TableHeap --> BufferPool
BTree --> BufferPool
BufferPool --> DiskManager
end
subgraph WAL["WAL Layer"]
Writer["WAL Writer<br/>Log + fsync"]
Recovery["RecoveryManager<br/>ARIES 3-Phase"]
end
subgraph Disk["Disk Files"]
data["data.db<br/>4KB Pages"]
wallog["wal.log<br/>Log Records"]
meta["minidb.meta<br/>Catalog PageID"]
end
Main --> E
E --> Executor
Executor --> TxnManager
Executor --> Writer
Executor --> Catalog
Executor --> BufferPool
TxnManager --> Writer
E --> Recovery
Recovery --> Writer
DiskManager --> data
Writer --> wallog
E --> meta
minidb/
โโโ .github/workflows/test.yml # CI๏ผGitHub Actions๏ผ
โโโ cmd/minidb/main.go # ใจใณใใชใผใใคใณใ๏ผREPL๏ผ
โโโ internal/
โ โโโ engine/engine.go # ใใผใฟใใผในใจใณใธใณ
โ โโโ storage/
โ โ โโโ page.go # ใใผใธๆง้ ๏ผ4KBๅบๅฎใตใคใบ๏ผ
โ โ โโโ disk.go # ใใฃในใฏใใใผใธใฃใผ
โ โ โโโ buffer.go # ใใใใกใใผใซ๏ผLRU๏ผ
โ โ โโโ heap.go # ใใผใใซใใผใ & ใซใฟใญใฐ
โ โโโ index/
โ โ โโโ btree.go # B-Treeใคใณใใใฏใน
โ โโโ sql/
โ โ โโโ lexer.go # ๅญๅฅ่งฃๆ
โ โ โโโ parser.go # ๆงๆ่งฃๆ
โ โ โโโ executor.go # ๅฎ่กใจใณใธใณ
โ โโโ txn/
โ โ โโโ transaction.go # ใใฉใณใถใฏใทใงใณ็ฎก็
โ โ โโโ mvcc.go # MVCCในใใใใทใงใใๅฏ่ฆๆง
โ โโโ wal/
โ โโโ log.go # ใญใฐใฌใณใผใๅฎ็พฉ
โ โโโ writer.go # ใญใฐๆธใ่พผใฟ
โ โโโ recovery.go # ARIESใชใซใใช
โโโ pkg/types/types.go # ๅ
ฑ้ๅๅฎ็พฉ
โโโ go.mod
โโโ README.md
# ใใซใ
cd minidb
go build -o minidb ./cmd/minidb
# ๅฎ่ก
./minidb -data ./mydata -buffer 1024
# ใชใใทใงใณ:
# -data ใใผใฟใใฃใฌใฏใใช (default: ./minidb-data)
# -buffer ใใใใกใใผใซใตใคใบ (default: 1024 pages = 4MB)minidb> CREATE TABLE users (id INT, name TEXT, active BOOL)
CREATE TABLE users (id=1)
minidb> INSERT INTO users (id, name, active) VALUES (1, 'Alice', true)
INSERT 1 (page=1, slot=0)
minidb> INSERT INTO users (id, name, active) VALUES (2, 'Bob', false)
INSERT 1 (page=1, slot=1)
minidb> SELECT * FROM users
โโโโโโโโผโโโโโโโโผโโโโโโโโโค
โ id โ name โ active โ
โโโโโโโโผโโโโโโโโผโโโโโโโโโค
โ 1 โ Alice โ true โ
โ 2 โ Bob โ false โ
โโโโโโโโผโโโโโโโโผโโโโโโโโโค
SELECT 2 rows
minidb> BEGIN
BEGIN (txn 5)
minidb> UPDATE users SET active = true WHERE id = 2
UPDATE 1
minidb> COMMIT
COMMIT (txn 5)
minidb> DELETE FROM users WHERE id = 1
DELETE 1
minidb> vacuum
VACUUM: removed 1 dead tuples.
users: scanned 2, removed 1minidb> CREATE TABLE products (id INT, name TEXT)
minidb> INSERT INTO products VALUES (1, 'Apple')
minidb> INSERT INTO products VALUES (2, 'Banana')
minidb> INSERT INTO products VALUES (3, 'Cherry')
-- ใซใฉใ ๅคใใผในใฎใคใณใใใฏในใไฝๆ
minidb> create index on products(id)
Index created on products(id)
-- ใคใณใใใฏใน็ต็ฑใฎ้ซ้ๆค็ดข๏ผใใซในใญใฃใณใงใฏใชใB-Treeๆข็ดข๏ผ
minidb> SELECT * FROM products WHERE id = 2
โโโโโโผโโโโโโโโโค
โ id โ name โ
โโโโโโผโโโโโโโโโค
โ 2 โ Banana โ
โโโโโโผโโโโโโโโโค
SELECT 1 rows
-- INSERT/UPDATEๅพใใคใณใใใฏในใฏ่ชๅใกใณใใใณในใใใ
minidb> INSERT INTO products VALUES (4, 'Date')
minidb> SELECT * FROM products WHERE id = 4
โโโโโโผโโโโโโโค
โ id โ name โ
โโโโโโผโโโโโโโค
โ 4 โ Date โ
โโโโโโผโโโโโโโค
SELECT 1 rows
-- VACUUMๅพใฏใคใณใใใฏในใๅๆง็ฏใใใ
minidb> DELETE FROM products WHERE id = 1
minidb> vacuum
VACUUM: removed 1 dead tuples.minidb> stats
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Database Statistics โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ WAL Current LSN: 15 โ
โ WAL Flushed LSN: 14 โ
โ Active Txns: 0 โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ Disk Pages: 2 โ
โ Tables: 1 โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ Buffer Pool Hits: 12 โ
โ Buffer Pool Misses: 2 โ
โ Buffer Pool Cached: 2 โ
โ Buffer Hit Rate: 85.7% โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโๅใณใณใใผใใณใใฎ็่ซ่ๆฏใจๅฎ่ฃ
ใฎ่ฉณ็ดฐใฏ docs/ ใซใพใจใใฆใใพใใ
| ใใญใฅใกใณใ | ๅ ๅฎน |
|---|---|
| ในใใฌใผใธใจใณใธใณ | ในใญใใใใผใธใใใฃในใฏใใใผใธใฃใใใใใกใใผใซใใใผใใซใใผใใใซใฟใญใฐ |
| WAL ใจ ARIES ใชใซใใช | Write-Ahead Logging ใฎใใญใใณใซใใญใฐใฌใณใผใๅฝขๅผใARIES 3 ใใงใผใบใชใซใใช |
| ใใฉใณใถใฏใทใงใณใจ MVCC | ใใฉใณใถใฏใทใงใณ็ฎก็ใในใใใใทใงใใๅ้ขใMVCC ๅฏ่ฆๆงใซใผใซ |
| B-Tree ใคใณใใใฏใน | B-Tree ใฎๅบ็คใใใผใใใฉใผใใใใๆค็ดขใปๆฟๅ ฅใปๅๅฒใขใซใดใชใบใ |
| SQL ใใผใตใผใจๅฎ่กใจใณใธใณ | ๅญๅฅ่งฃๆใๅๅธฐไธ้ใใผใตใผใๅ SQL ๆใฎๅฎ่กใใญใผ |
1. ใใผใธๆง้ (storage/page.go) โ ่ฉณ็ดฐ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Header (28 bytes) โ
โ PageID(4) | Type(1) | Reserved(3) โ
โ LSN(8) | SlotCount(2) โ
โ FreeSpaceOffset(2) | FreeSpaceEnd(2)โ
โ NextPageID(4) | Reserved(2) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Free Space โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ Tuple Data (grows downward) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Slot Array (grows upward) โ โ
โ [offset|len] [offset|len] ... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ใใผใใใผใธใฏ NextPageID ใใฃใผใซใใซใใใชใณใฏใชในใใง้ฃ็ตใใใพใ๏ผ้ฃ็ถใใผใธ็ชๅทใไปฎๅฎใใพใใ๏ผใ
2. ใใใใกใใผใซ (storage/buffer.go) โ ่ฉณ็ดฐ
type BufferPool struct {
pages map[PageID]*Page // ใใผใธใญใฃใใทใฅ
lruList *list.List // LRU้ ๅบ
capacity int // ๆๅคงใใผใธๆฐ
}
// ใใผใธๅๅพ: ใญใฃใใทใฅใซใใใฐใใใใใชใใใฐใใฃในใฏใใ่ชญใ
func (bp *BufferPool) FetchPage(pageID) (*Page, error) {
if page := bp.pages[pageID]; page != nil {
bp.hits++
bp.touchLRU(pageID) // LRUใๆดๆฐ
return page, nil
}
bp.misses++
page := bp.diskManager.ReadPage(pageID)
bp.evictIfNeeded() // ๅฟ
่ฆใชใLRUใใผใธใ่ฟฝใๅบใ
bp.pages[pageID] = page
return page, nil
}3. WALๆธใ่พผใฟ (wal/writer.go) โ ่ฉณ็ดฐ
// ใณใใใๆใฎๅฆ็
func (w *Writer) LogCommit(txnID) (LSN, error) {
// 1. COMMITใฌใณใผใใใใใใกใซ่ฟฝๅ
lsn := w.Append(&LogRecord{Type: COMMIT, TxnID: txnID})
// 2. ใ้่ฆใใใฃในใฏใซๅผทๅถๆธใ่พผใฟ๏ผfsync๏ผ
// ใใใซใใใใฏใฉใใทใฅใใฆใใณใใใใๅคฑใใใชใ
w.Force(lsn)
return lsn, nil
}4. MVCCๅฏ่ฆๆง (txn/mvcc.go) โ ่ฉณ็ดฐ
func (s *Snapshot) IsVisible(tuple *Tuple) bool {
// ไฝๆใใฉใณใถใฏใทใงใณใๅฏ่ฆใ๏ผ
if !s.isTxnVisible(tuple.XMin) {
return false
}
// ๅ้คใใใฆใใชใใ๏ผ
if tuple.XMax == InvalidTxnID {
return true // ๅ้คใใใฆใใชใ
}
// ๅ้คใใฉใณใถใฏใทใงใณใใพใ ่ฆใใชใ๏ผ
if !s.isTxnVisible(tuple.XMax) {
return true // ใพใ ๅ้คใฏ่ฆใใชใ
}
return false // ๅ้คๆธใฟ
}5. B-Treeใคใณใใใฏใน (index/btree.go) โ ่ฉณ็ดฐ
[30|60] โ ๅ
้จใใผใ
/ | \
[10|20] [40|50] [70|80] โ ใชใผใใใผใ
โ โ โ
RIDs RIDs RIDs โ ่กไฝ็ฝฎ๏ผPageID + SlotNum๏ผ
ใซใฉใ ๅคใใฝใผใ้ ไฟๆใจใณใณใผใใฃใณใฐใงใญใผๅใใSELECT ... WHERE col = val ใงใคใณใใใฏในๆข็ดขใ่กใใINSERT/UPDATE ๆใซใคใณใใใฏในใฏ่ชๅใกใณใใใณในใใใVACUUM ๆใซๅๆง็ฏใใใใ
6. ARIESใชใซใใช (wal/recovery.go) โ ่ฉณ็ดฐ
Phase 1: Analysis
โโ ใญใฐใ่ตฐๆปใใฆATT๏ผใขใฏใใฃใTxn๏ผใจDPT๏ผใใผใใฃใใผใธ๏ผใๅๆง็ฏ
Phase 2: Redo
โโ DPTใฎๆๅฐRecLSNใใๅ
จใฆใฎๅคๆดใๅ้ฉ็จ๏ผใณใใใๆธใฟ/ๆชใณใใใไธกๆน๏ผ
Phase 3: Undo
โโ ATTๅ
ใฎๆชใณใใใTxnใPrevLSNใใงใผใณใ้้ ใซ่พฟใฃใฆใญใผใซใใใฏ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ File Header (16 bytes) โ
โ Magic: "MINIDBPD" | Version | NumPagesโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Page 0 (4096 bytes) - Catalog โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Page 1 (4096 bytes) - Table Data โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Page 2 (4096 bytes) - ... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ File Header (16 bytes) โ
โ Magic: "MINIDBWA" | Version โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ LogRecord 1: [len][LSN|PrevLSN|TxnID|...โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ LogRecord 2: [len][LSN|PrevLSN|TxnID|...โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- ARIES่ซๆ: "ARIES: A Transaction Recovery Method" (Mohan et al., 1992)
- ๆธ็ฑ: "Database Internals" by Alex Petrov
- PostgreSQLใฝใผใน:
src/backend/access/transam/,src/backend/storage/buffer/ - CMU 15-445: Database Systems (Andy Pavlo)
| ๆฉ่ฝ | ่ชฌๆ |
|---|---|
| WALๅง็ธฎ | ๅคใใญใฐใฎๅ้คใปๅง็ธฎ |
| ไธฆๅในใญใฃใณ | ่คๆฐในใฌใใใงใฎใใผใใซในใญใฃใณ |
| ใฏใจใชใชใใใฃใใคใถ | ๅฎ่ก่จ็ปใฎๆ้ฉๅ |
| JOIN | ่คๆฐใใผใใซใฎ็ตๅ |
| ่คๅใคใณใใใฏใน | ่คๆฐใซใฉใ ใซใพใใใใคใณใใใฏใน |
| ้ใฆใใผใฏใคใณใใใฏใน | ้่คใญใผใฎใตใใผใ๏ผ็พๅจใฏๅไธใญใผใงไธๆธใ๏ผ |
MIT License