惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
罗磊的独立博客
H
Help Net Security
I
Intezer
G
Google Developers Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Troy Hunt's Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
J
Java Code Geeks
S
Security Affairs
T
The Blog of Author Tim Ferriss
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
The GitHub Blog
The GitHub Blog
F
Full Disclosure
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
腾讯CDC
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
T
Threatpost
D
DataBreaches.Net
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
博客园 - 【当耐特】
L
LINUX DO - 最新话题
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
S
Securelist
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Help Net Security
Help Net Security
P
Proofpoint News Feed
Project Zero
Project Zero
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 叶小钗

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
[🗄️DataBase] Database Transactions 底層到底做了什麼:從記憶體到磁碟
Mercy · 2026-06-13 · via DEV Community

目錄

  1. 為什麼要理解這件事
  2. 電腦儲存層級:從 Register 到 SSD
  3. 資料庫引擎核心架構:Page Cache、WAL、Checkpoint
  4. 實際範例
  5. 總結

1. 為什麼要理解這件事

不管用哪個資料庫、哪種語言,你每天都在做類似的事

# Python + psycopg2 (PostgreSQL)
cur.execute("INSERT INTO roles (name) VALUES (%s)", ("admin",))
conn.commit()

// C# + EF Core
_db.Roles.Add(role);
await _db.SaveChangesAsync();
await tx.CommitAsync();

// Node.js + pg (PostgreSQL)
await client.query("INSERT INTO roles (name) VALUES ($1)", ["admin"]);
await client.query("COMMIT");

但你真的知道這些 API 背後發生了什麼事嗎?

  • ExecuteNonQuery() / SaveChangesAsync() 執行後,資料到底在哪?
  • 什麼叫「在記憶體裡」?
  • Flush 和 Commit 有什麼差別?
  • Transaction 是怎麼保護你的資料的?

這篇文章會從 CPU 如何存取資料開始,一步步講到資料庫引擎怎麼保證你的資料不遺失。


2. 電腦儲存層級:從 Register 到 SSD

2.1 CPU Register(暫存器)

CPU 晶片內部有幾十個暫存器,每個 64-bit(以現代 x64 CPU 來說)。資料要被運算(加減乘除、比對大小),一定要先載到暫存器。

mov rax, [memory_address]   ; 從 RAM 搬到 CPU 暫存器
add rax, 1                  ; 在 CPU 裡面加 1
mov [memory_address], rax   ; 存回 RAM

前面例子寫的 role.name = "新名稱",編譯器編譯後最終會變成好幾條這種機器指令,把值從一個 RAM 位址搬到 CPU,改完再搬回去。

屬性
容量 ~幾十 bytes
速度 ~0.3 ns
斷電是否消失

2.2 RAM(主記憶體)

RAM(Random Access Memory)是電容 + 電晶體做成的儲存陣列,每個 cell 儲存 1 bit 的電荷。優點是讀寫極快,缺點是斷電就全部消失

256 GB RAM 大概有 2 兆個這樣的 cell。

你的變數全部存在這裡。
當你修改一個變數,你修改的是 RAM 中某個位址上的 byte。

屬性
容量 ~GB ~ TB
速度 ~50-100 ns
斷電是否消失

2.3 SSD / HDD(硬碟)

硬碟是最終儲存資料的地方。HDD 用磁碟片,SSD 用 NAND Flash 晶片。

屬性 HDD SSD
速度 ~5-10 ms ~10-100 μs
比 RAM 慢 ~100,000 倍 ~1,000 倍
斷電是否消失

3. 資料庫引擎核心架構:Page Cache、WAL、Checkpoint

不管哪個資料庫,設計目標都一樣:提供 ACID 保證,同時要有夠好的效能

直接讀寫磁碟太慢了(比 RAM 慢 1000~100000 倍),所以所有資料庫都有一個核心機制:

你的程式 (Application)                    Database Engine
┌─────────────────────────┐        ┌──────────────────────────────────┐
│  Application Layer      │  SQL   │         Page Cache (RAM)          │
│  ┌───────────────────┐  │ ─────→ │  ┌──────┬──────┬──────┬───────┐  │
│  │ 資料 (物件/row)    │  │        │  │Page 1│Page 2│Page 3│ ...   │  │
│  │ SQL 語句           │  │        │  │ dirty│ clean│ dirty│       │  │
│  └───────────────────┘  │        │  └──┬───┴──────┴──┬───┴───────┘  │
│                         │        │     │             │               │
│                         │        │     ↓             ↓               │
│                         │        │  Background    Background         │
│                         │        │  Writer        Checkpoint         │
│                         │        │     │             │               │
└─────────────────────────┘        │     ↓             ↓               │
                                    │  Write-Ahead Log  Data Files     │
                                    │  (WAL / Redo Log / Tx Log)       │
                                    │  (磁碟)           (磁碟)          │
                                    └──────────────────────────────────┘

假設你寫了一行:

UPDATE users SET name = 'Alice' WHERE id = 1;

你的程式把這行 SQL 丟給資料庫引擎。然後呢?

--

第一站:Application RAM(你的程式記憶體)

當你的程式執行:

var role = new Role { Name = "管理員" };
db.Roles.Add(role);

這筆資料只在你程式的記憶體裡(.NET managed heap / Python heap / 等等),還沒透過任何 API 送出去。

這時如果斷電,這筆資料一定消失。


第二站:Flush(送出 SQL)

db.SaveChangesAsync();          // EF Core
// 或
cmd.ExecuteNonQuery();          // ADO.NET
// 或
cur.execute("INSERT ...");     // psycopg2 (Python)

這步做了:

  1. 應用程式把 SQL 或資料透過 TCP/IP(或共用記憶體)送到 Database Engine
  2. Database Engine 開始接手處理
  3. 資料正式離開你的行程記憶體,進入資料庫的管轄範圍

第三站:Page Cache(Buffer Pool)

資料庫不直接讀寫磁碟,原因很簡單,因為磁碟太慢了。
所以它在啟動時會跟 OS 要一大塊 RAM,叫 Page Cache
每個資料庫叫法不同,做的事一模一樣:

資料庫 Page Cache 名稱 位置
PostgreSQL shared_buffers 資料庫自己的記憶體
MySQL/InnoDB innodb_buffer_pool 資料庫自己的記憶體
SQL Server Buffer Pool 資料庫自己的記憶體
SQLite Page Cache 行程內記憶體

資料庫收到你的 UPDATE 後,第一步是找到那筆資料所在的 Page:

  1. 先在 Page Cache 找有沒有這個 Page
  2. 有 → 直接拿來用(Cache Hit)
  3. 沒有 → 從磁碟載入 Page Cache(Cache Miss)

然後直接在這個 Page 上修改,再把該 Page 標記為 Dirty Page跟磁碟版本不一致)。

但 Dirty Page 不能一直待在記憶體裡,不然機器斷電資料就不見了。


第四站:WAL(Write-Ahead Log)

所以資料庫做了一件非常重要的事,
在把 Dirty Page 寫回磁碟的資料檔之前,先把修改紀錄寫到 WAL。

流程有四步:

1. 收到 UPDATE / INSERT / DELETE SQL
2. 在 Page Cache 修改對應的 Page(Dirty)
3. 把「我做了什麼修改」寫到 Transaction Log(磁碟)
4. 回傳給用戶「完成了」

WAL 是順序寫入(sequential write),速度快。
它只是 append-only 的日誌,不會回頭修改舊紀錄。

一旦 WAL 寫完,這筆修改就算安全了,就算下一秒機器崩潰或是斷電,重啟時只要 replay WAL,就能復原到你剛修改完的狀態。

這時候資料檔可能還沒有被更新,但 Transaction Log 已經寫了。如果斷電,資料庫重新啟動時會讀 Transaction Log:

  • 有 COMMIT 記錄 → Redo:把還沒寫回磁碟的修改重新套用
  • 沒有 COMMIT 記錄 → Undo:把已做的修改還原

第五站:Commit

await tx.CommitAsync();       // EF Core
// 或
tx.Commit();                   // ADO.NET
// 或
conn.commit();                 // Python DB-API
// 或
COMMIT;                        // CLI

這行在 Transaction Log 中寫入一筆 COMMIT 記錄。

從這一刻起:

  • 如果斷電,資料庫 Recovery 會把這筆資料還原(Redo)
  • 其他連線可以看到這筆資料(隔離級別決定何時看到)

Flush vs Commit:差別在哪

用生活比喻,想像你是一個廚師,要做一道菜給客人:

動作 對應的程式操作 比喻
備料切菜 建立物件 / 組裝 SQL 在流理台上準備材料
下鍋煮 Flush(送出 SQL / SaveChanges) 煮好了,放在廚房檯面上
決定上菜 Commit 端出去給客人吃
覺得太鹹倒掉 Rollback 倒掉重做,反正客人沒看到
  • Flush: 把菜做好放在廚房檯面上,菜已經熟了(資料庫已執行),但還沒端出去(還沒 Commit),客人看不到,萬一覺得不好吃還可以倒掉(Rollback)
  • Commit: 端出去給客人吃,一旦端出去了就來不及了(永久的)

第六站:Background Writer

Dirty Page 還是要寫回資料檔的,但資料檔是隨機寫入(random write),慢很多。
如果一次大量寫,使用者的查詢就會被卡住。

所以 Background Writer 在後台默默、慢慢地把 Dirty Page 刷回磁碟的資料檔。每次只刷一點點,不搶頻寬,讓使用者感覺不到它的存在。


第七站:Checkpoint

Background Writer 平常一直在刷,但總有一些 Page 它來不及刷,或累積太多 Dirty Page。

Checkpoint 的工作就是定時強制把所有髒 Page 刷回磁碟
做完之後告訴 WAL:「這之前的日誌都已經同步了,可以砍掉了。」

這樣 WAL 不會無限膨脹,也縮短了崩潰後 recovery 的時間,只需要 replay checkpoint 之後的 WAL 就夠了。


崩潰怎麼辦:Recovery

機器永遠會 crash,這時就需要 ARIES 演算法來救。

ARIES(Algorithm for Recovery and Isolation Exploiting Semantics)是資料庫崩潰後如何自動救回來的標準流程,所有現代關聯式資料庫(InnoDB、SQL Server、PostgreSQL、Oracle)都在用:

  1. Analysis — 掃 WAL,查出哪些 Page 是髒的、哪些交易還沒結束
  2. Redo — 從上一個 checkpoint 開始,把所有修改重新做一遍(不管有沒有寫回資料檔),確保資料檔跟 crash 瞬間一致
  3. Undo — 把 crash 時還沒 commit 的交易全部還原

不管你 crash 前做過什麼,redo 全部重做一次,再把沒做完的 undo 掉,結果就是對的。

之所以叫 ARIES,是因為它利用 WAL 裡的語義資訊(知道每筆修改對應哪個 page、哪個 transaction),不需要猜測。

總結流程:

先寫 WAL(按順序寫,保證崩潰安全)→ Background Worker 慢慢刷 Dirty Page 回資料檔(隨機寫)→ Checkpoint 定時總整理、截斷 WAL


4. 實際範例

用一個典型的業務情境:建立一個新角色,同步身分認證資料,記錄稽核日誌。

4.1 沒有 Transaction

# Python pseudo code
db.roles.insert({"name": "admin"})
# 隱含 AUTO COMMIT

ensure_identity_role("admin")
# 內部也有自己的 AUTO COMMIT

audit_service.log("RoleCreated", "admin")
# 隱含 AUTO COMMIT

資料流向:

第 1 次 flush →  DB Page Cache: ✅ INSERT INTO roles
                 Transaction Log:  ✅ INSERT + AUTO COMMIT
                 → 已「永久」

第 2 次 flush →  DB Page Cache: ✅ INSERT INTO identity_roles
                 Transaction Log:  ✅ INSERT + AUTO COMMIT
                 → 又「永久」

第 3 次 flush →  DB Page Cache: ✅ INSERT INTO audit_logs
                 Transaction Log:  ✅ INSERT + AUTO COMMIT
                 → 又「永久」

如果第 1 次 flush 後、第 2 次 flush 前斷電:

資料表 (Table) DB Recovery 後的狀態 關鍵原因說明
roles 存在 第一次 Flush 時,觸發 AUTO COMMIT 永久落地
identity_roles 不存在 寫入前系統已崩潰,Transaction Log 無此記錄
audit_logs 不存在 寫入前系統已崩潰,Transaction Log 無此記錄

資料庫處於不一致狀態,而且無法恢復。

4.2 有 Transaction

with db.begin_transaction() as tx:
    db.roles.insert({"name": "admin"})
    ensure_identity_role("admin")
    audit_service.log("RoleCreated", "admin")
    tx.commit()

資料流向:

執行動作 / 程式碼 DB Page Cache 狀態 Transaction Log 狀態 結果說明
db.begin_transaction() 無變更 BEGIN TRAN 交易正式開始,開啟安全保護傘
roles.insert() INSERT roles INSERT (無 COMMIT) 資料暫存於快取,尚未真正生效
ensure_identity_role() INSERT identity_roles INSERT (無 COMMIT) 資料暫存於快取,尚未真正生效
audit_service.log() INSERT audit_logs INSERT (無 COMMIT) 資料暫存於快取,尚未真正生效
tx.commit() 保持不變 (等待 Checkpoint) COMMIT 日誌強制落地,三筆資料同時正式生效

如果 commit 前斷電:

DB Recovery 後:
  Transaction Log 中沒有 COMMIT 記錄
  → 全部三筆 INSERT 都被 Rollback(Undo)
  → 資料庫像沒發生過一樣

重新執行一次即可,不會有任何殘留資料。


5. 總結

資料從應用程式到磁碟,並不是一步到位

它會先存在 Application RAM,接著透過 Flush 送進 Database Engine,在 Page Cache 中修改資料頁,並寫入 WAL / Transaction Log

只有當 Transaction Log 中出現 COMMIT 記錄時,這筆交易才正式成立。

至於 Dirty Page 什麼時候真正寫回 Data Files,通常是之後由 Checkpoint背景程序 完成。

整個流程為:

Application RAM → Flush → Page Cache + WAL → Commit → Checkpoint → Data Files