髒讀(Dirty Read)是什麼?

資料庫交易讀取到另一個尚未提交之交易所寫入的中間態資料,造成資料不一致的現象。|本頁含完整原理、應用場景、iPAS 考試重點與 3 個常見問答。

英文
Dirty Read
主題標籤
資料庫、交易管理、並行控制
考點定位
非 iPAS 核心術語
最後更新
2026/06/22
髒讀(Dirty Read)是什麼? 資料庫交易管理
術語快查

搜尋意圖: 如果你在找「髒讀 是什麼」或「髒讀 和相近概念差在哪」,先看這頁的短定義、完整說明與延伸比較。

TL;DR: 資料庫交易讀取到另一個尚未提交之交易所寫入的中間態資料,造成資料不一致的現象。

實用情境: 適合用在閱讀 AI 文章、產品文件或和同事討論時,先用一頁快速對齊概念。

下一步: 先讀完定義,再往下看延伸比較與對應工具,把概念轉成實際應用。

資料庫交易讀取到另一個尚未提交之交易所寫入的中間態資料,造成資料不一致的現象。

髒讀(Dirty Read)是資料庫管理系統(DBMS)並行控制理論中定義的三種標準讀取異常之一,另外兩種是不可重複讀(Non-Repeatable Read)與幻象讀(Phantom Read)。理解髒讀對於設計高並發的 AI 系統(如即時特徵工程、線上機器學習、訓練資料管線)至關重要,因為錯誤的隔離等級可能導致模型訓練或推論時讀取到不一致的資料。

什麼是「髒」資料

在資料庫交易(Transaction)的語境下,「髒資料」(dirty data)指的是已被某個交易修改、但該交易尚未執行 COMMIT(提交)的資料。這些資料存在於記憶體緩衝區(buffer)中,尚未被持久化到磁碟,代表一種「中間狀態」。如果另一個並行交易在此時讀取了這些中間態資料,就發生了髒讀。

具體場景說明

以銀行轉帳為例:

  1. 交易 T1 開始執行「從帳戶 A 扣款 1000 元,加到帳戶 B」的操作,先更新帳戶 A(餘額由 5000 變 4000),尚未更新帳戶 B,也尚未 COMMIT。
  2. 此時交易 T2 讀取帳戶 A 的餘額,得到 4000(而非原始的 5000)。
  3. T1 因某種錯誤執行 ROLLBACK,帳戶 A 恢復為 5000。
  4. T2 基於讀取到的 4000 繼續後續計算(如計算信用額度),結果與實際狀態不符。

T2 讀到的 4000 就是「髒資料」,整個過程就是一次髒讀。

ANSI/ISO SQL 隔離等級標準

SQL 標準定義了四個交易隔離等級,不同等級允許或防止不同類型的讀取異常:

讀未提交(Read Uncommitted):隔離程度最低,允許髒讀、不可重複讀、幻象讀發生。在此等級下,交易可以讀取其他未提交交易的修改。極少在生產環境使用,除非對一致性要求極低且追求最高並發量的場景。

讀已提交(Read Committed):防止髒讀,但允許不可重複讀與幻象讀。每次讀取只看到已提交的資料,是 PostgreSQL、Oracle、SQL Server 等主流資料庫的預設隔離等級。

可重複讀(Repeatable Read):防止髒讀與不可重複讀,但允許幻象讀。在同一個交易中多次讀取同一欄位會得到相同結果。MySQL InnoDB 的預設隔離等級。

序列化(Serializable):隔離程度最高,防止所有讀取異常,等同於讓所有交易序列執行。對並發性能影響最大,通常需要悲觀鎖或 MVCC(多版本並發控制)技術支援。

防止髒讀的技術機制

主流資料庫防止髒讀的機制主要有兩種:

鎖定機制(Locking):寫入交易在修改資料時加上排他鎖(X-Lock),讀取交易必須等到寫入交易 COMMIT 或 ROLLBACK 後才能獲取共享鎖(S-Lock)讀取資料。這是傳統的悲觀並發控制(Pessimistic Concurrency Control)方法。

多版本並發控制(MVCC, Multi-Version Concurrency Control):每次資料修改不直接覆蓋原值,而是建立新版本,舊版本保留。讀取交易根據交易開始時間戳選擇對應版本,看不到未提交的新版本。PostgreSQL、MySQL InnoDB 等均採用 MVCC,讀寫操作互不阻塞,性能較純鎖定方案更佳。

髒讀在 AI 系統中的影響

特徵工程管線:即時特徵計算(如使用者行為統計)若在資料寫入過程中被讀取,可能導致模型接收到不完整的特徵向量,影響推論準確性。

訓練資料管線:ETL 或資料同步過程中若存在髒讀風險,可能使訓練資料集包含回滾前的暫態值,引入系統性雜訊。

線上學習系統:實時更新模型參數時,多個工作執行緒若讀取到彼此未完成的梯度更新,可能導致訓練不穩定。

資料標注平台:多位標注員同時編輯同一批資料時,若缺乏適當隔離,可能出現標注結果不一致的問題。

最佳實踐建議

對大多數業務應用,建議使用讀已提交(Read Committed)或以上隔離等級,以避免髒讀帶來的資料一致性問題。若應用有嚴格的金融或審計需求,應評估使用序列化(Serializable)等級或搭配樂觀鎖機制。在設計高並發 AI 資料管線時,應明確記錄每個關鍵讀取操作的隔離等級選擇與其理由,作為系統文件的一部分。

在 iPAS AI 應用規劃師認證中,髒讀屬於資料庫與資料管理的考核範疇,考生需理解其定義、發生條件、與隔離等級的對應關係,以及在 AI 系統資料管線設計中的實際影響。

常見問題

髒讀和不可重複讀有什麼區別?

兩者都是並發交易下的讀取異常,但觸發條件不同。髒讀發生在讀取到「未提交」的資料:交易 A 讀取了交易 B 尚未 COMMIT 的修改,若 B 後來 ROLLBACK,A 就讀到了從未真正存在的資料。不可重複讀(Non-Repeatable Read)則發生在讀取到「已提交」的修改:交易 A 在同一個交易中兩次讀取同一欄位,期間交易 B 提交了修改,導致兩次讀取結果不同。防止髒讀只需讀已提交(Read Committed)等級;防止不可重複讀則需可重複讀(Repeatable Read)等級。兩者的嚴重性不同,髒讀通常更危險,因為它讀到的資料可能在資料庫歷史上根本不存在。

在預設設定下,常見資料庫(MySQL、PostgreSQL)會有髒讀問題嗎?

不會,主流資料庫的預設隔離等級都能防止髒讀。PostgreSQL 和 Oracle 的預設隔離等級是讀已提交(Read Committed),天然防止髒讀;MySQL InnoDB 的預設隔離等級是可重複讀(Repeatable Read),同樣防止髒讀且保護更強。只有當開發者明確將隔離等級設為「讀未提交(Read Uncommitted)」時,才會允許髒讀發生。在實際開發中,除非有特殊性能需求且能接受資料不一致,否則不建議使用讀未提交等級。如果在應用層面發現資料不一致,更常見的原因是應用程式邏輯錯誤或缺少適當的交易邊界,而非資料庫隔離等級設定。

NoSQL 資料庫(如 MongoDB、Redis)也有髒讀問題嗎?

NoSQL 資料庫對交易和隔離等級的支援程度差異很大。MongoDB 自 4.0 版起支援多文件 ACID 交易,提供類似 Read Committed 等級的隔離保護;在單文件操作上,MongoDB 原生保證原子性,不存在髒讀。Redis 支援 MULTI/EXEC 交易塊,在 EXEC 執行前命令只是排隊,無法中途讀取到部分狀態,因此不會有傳統意義的髒讀;但 Redis 的 WATCH 機制(樂觀鎖)若設計不當,可能出現其他類型的競態條件。整體而言,NoSQL 資料庫通常在一致性與可用性之間做不同取捨(CAP 定理),評估時需查閱各資料庫的具體文件,而非直接套用 SQL 的隔離等級概念。