跳至主要內容
論文精煉 · Transactions

The Transaction Concept: Virtues and Limitations

把 atomicity、consistency、durability 立為交易的三大性質,再誠實指出巢狀與長時間交易會在哪裡撐不住。

作者Jim Gray(Tandem Computers Incorporated,加州 Cupertino) 發表於第七屆 International Conference on Very Large Databases,1981 年 9 月;另發表為 Tandem 技術報告 TR 81.3,1981 年 6 月 年份1970 年代末–1980 年代
閱讀原始論文 PDF 所有論文

一口氣講完 — 整篇論文的濃縮

Gray 把交易這個他上溯到契約法的概念,收斂成三個性質:consistency(轉換必須遵守系統的約束)、atomicity(要嘛全發生、要嘛完全不發生)、durability(一旦提交就不可撤銷)。他主張交易是撰寫容錯程式最合適的抽象,因為由 fail-fast 模組與 process pair 堆出來的 NonStop 系統雖然很可靠,卻細節繁瑣到難以直接寫應用程式,而 BEGIN、COMMIT、ABORT 三個動詞可以把這些全部藏起來。接著他把當時僅有的兩條實作路線並排比較:time-domain addressing 讓物件永不覆寫,位址是名稱加上時間,更新變成「演進」;logging 加上鎖定則用 DO-UNDO-REDO 日誌記下新舊值,再靠鎖把未提交的輸出遮住。Gray 的結論是兩者在內部結構上其實比表面看起來相似得多:帶時戳的日誌本身就是一份版本歷史,而版本系統把舊版本做垃圾回收之後,長得也很像一份日誌。全文最後三分之一是最誠實的部分:這套模型無法讓交易巢狀、假設交易只活幾分鐘而非幾週、也塞不進一般程式語言,而他提出的解法是刻意用 atomicity 去換的。

在這篇論文之前 — 它所降落的世界

到了 1981 年,計算機界從會計實務繼承來的紀律其實已經被悄悄丟掉了。磁帶時代的批次作業讀入舊主檔加上當天的卡片、產出新主檔,舊狀態從不被破壞;直接存取的磁碟出現後,只改寫變動的那一小塊變得太划算,Gray 說大多數磁碟系統就這樣被就地更新(update in place)誘惑了。並行控制在生產環境裡仍屬經驗法則:IMS/360 曾試圖事先宣告每個交易的讀寫集合、在排程時做交集判斷,這套 intent scheduling 在 1973 年就被放棄。容錯又是另一門獨立手藝,1960 年代末起用鏡像磁碟,在 Tandem 則靠 process pair,由主行程在每次操作前把狀態 checkpoint 給備援行程,而 Gray 直言這種接手非常微妙,重新同步請求端與伺服端極其棘手。同時,應用程式設計師只能自己土法煉鋼地處理跨多步驟的復原:在 IMS 用 scratchpad、在 CICS 用 transaction work area,把自己的日誌當成一筆記錄寫進資料庫,因為系統對跨越多次互動的工作根本什麼都沒提供。

問題 — 當時真正壞掉的地方

  • 就算真的做出一台完美的系統,它仍然會失敗,因為把系統導入環境的人會犯應用程式錯誤、操作系統的人會犯資料輸入與流程錯誤,因此至少每 100 筆交易就有 1 筆會因為輸入錯誤或授權錯誤而中止,這是硬體與軟體再完美都擋不住的。
  • 即使拿到一台高可用系統,在上面寫容錯應用仍然不容易:備援行程接手時必須從主行程斷掉的地方繼續運算,又不能把這次失敗擴散給其他行程,而請求端與伺服端的重新同步極其微妙。
  • 就地更新會直接毀掉舊值,違反了「帳簿永不塗改」這條會計鐵律,於是除非刻意加上某種機制,系統裡沒有任何東西記得該怎麼回到上一個一致狀態。
  • 交易若並行執行,某個交易可能讀到另一個交易的更新或訊息,而後者稍後卻中止;要撤銷前者就得撤銷後者,但後者可能早已提交,因此根本無法撤銷。
  • 交易不能巢狀包在交易裡,所以一位替客戶訂機票、租車與旅館的旅行社業務,完全無法表達這個「客戶眼中的單一交易」,因為航空公司與旅館看到的是各自獨立且已經提交的交易。
  • 現有模型假設交易只活幾分鐘而不是幾週,可是旅遊、保險、政府與電子郵件類應用會產生數以千計、動輒數日數週的並行交易,而死結頻率隨多工程度的平方、以及交易大小的四次方成長。

核心概念 — 主要貢獻,以及它們為何成立

交易概念源自契約法

Gray 不從計算機出發,而是從契約談起:雙方先協商,再以共同簽署、握手或點頭讓約定生效;若彼此不夠信任,就找一位中介(escrow officer)來協調提交。他從這裡直接讀出三個性質:consistency 是交易必須遵守合法的協定,atomicity 是要嘛所有人都受契約約束、要嘛都不受,durability 是一旦提交就不可撤銷。這個類比之所以重要,是因為它同時提供了修補機制:契約不能說廢就廢,錯誤的交易只能靠後續的補償交易(compensating transaction)來調整。這正是後面用來搶救巢狀交易與長時間交易的同一招,也說明了補償在本文裡是頭等概念,而不是事後補丁。

你不需要一台完美的系統

要拿到 atomicity 與 durability,一條路是打造永不故障的硬體與軟體,但 Gray 認為這條路既做不到也沒必要。Von Neumann 證明了可以用不可靠的元件組出可靠系統,但他那套扁平的神經網模型必須用 20,000 條線換 1 條線,因為鏈上任一環節故障就會斷掉整條鏈。電腦系統則是階層式地由不到約 100 個模組組成,而且每個模組都可以做成 fail-fast:要嘛正確運作,要嘛偵測到自己故障然後什麼都不做。fail-fast 加上備品、再加上雙工,就能把平均故障間隔以月計的模組,變成平均故障間隔以世紀計的系統,所以一台每一千年才壞一次的系統就已經夠好了。

把交易當成容錯的介面

Gray 力挺交易的主要理由不是抽象的正確性,而是可程式性。另一條路是讓主行程在每次操作前把狀態 checkpoint 給備援行程,但那等於逼每一位應用作者都去處理接手與重新同步。相對地,把一次運算所涉及的所有行程收攏成一個交易,出錯時把它們一起重設回交易的初始狀態,再由新的行程從 save point 或從頭繼續。實作交易機制的人仍然得直面 process pair 與 NonStop 的種種細節,但在那之後,所有程式設計師寫的就只是普通程式碼再加三個動詞:BEGIN-TRANSACTION、COMMIT-TRANSACTION、ABORT-TRANSACTION。

time-domain addressing 的統一解

在 Reed 的提案裡,物件從不被修改,而是被「演進」:實體 E 帶著一串值,每個值在一段時間區間內有效,而位址從單純的名稱變成名稱加上時間。每個交易都被指派一個唯一的執行時間,它所有的讀與寫都以那個時間來解讀,所以在時間 T3 讀 E,拿到的就是當時的當前值。Reed 指出這同時解決了並行控制問題與可靠性問題,因為同一份版本歷史既提供復原能力,也提供一致的讀取。它還額外送給應用程式完整的時間旅行能力,可以直接問「年底結帳時帳面長什麼樣子?」

日誌與版本其實是同一件事

這是全文最鋒利的結構性觀察。日誌系統為了讓 undo 與 redo 具備可重啟性,必須替物件或物件片段標上版本號,因此大多數日誌方案裡本來就藏著一種 time-domain addressing。反過來說,只要每筆日誌記錄都帶上時戳,日誌就實作了 time-domain addressing;而 time-domain 系統把舊版本垃圾回收之後,產物看起來非常像一份日誌,並且同樣得用鎖來序列化物件表頭的更新。Gray 由此斷言:儘管兩者外觀差異明顯,內部結構其實相似遠多於相異,並轉述 Reed 的主張——每一個鎖定與日誌的技巧,在 time-domain addressing 裡都有對應的技巧。

用補償處理無法撤銷的事

當某個步驟已經在別的組織那邊提交,任何復原管理員都不可能把它回滾,只有補償交易能反轉它。因此 Gray 在交易模型裡加進第四類組成:巢狀交易,它可以透過呼叫補償交易來撤銷,與 unprotected、protected、real 三類動作並列。巢狀交易執行後會以副作用的形式回傳自己的補償交易名稱與參數,父交易把這份資訊寫進自己的日誌,父交易被撤銷時就據以呼叫。他也很坦白:巢狀交易與 protected action 的差別正在於它的效果在父交易提交前就已經被外界看見,所以它保有一致轉換與「提交或補償」的紀律,卻直接放棄了 atomicity。

交易應該進入程式語言

Gray 主張把 BEGIN、SAVE、COMMIT、ABORT 做成語言層的動詞,並且推導出一個新的抽象資料型別必須提供什麼才能參與交易。每當定義一個新的物件型別與其操作,該型別上的 protected 操作就必須產生 undo 與 redo 日誌記錄,若物件是共享的還要取得鎖;型別管理員(type manager)必須提供 UNDO 與 REDO 程序,能吃下這些日誌記錄並重建物件的舊版與新版。real 操作必須延後,讓日誌管理員在提交時回頭呼叫型別管理員真正執行;巢狀操作則必須把補償交易的名稱與輸入放進 undo 日誌。型別管理員還得參與系統 checkpoint 與重啟。Gray 同時承認他並不確定這在一般情況下行得通,也擔心日誌的效能代價可能高到無法接受。

運作方式 — 具體的機制

系統狀態、約束,與三類動作

系統狀態由值可變的記錄與裝置組成,再加上關於這些值、以及關於允許哪些轉換的斷言,Gray 稱之為系統一致性約束(system consistency constraints)。交易就是一組共同構成一次一致轉換的動作,把狀態從一個一致狀態帶到另一個一致狀態。動作依可逆性分成三類:unprotected 動作不需要被撤銷或重做,例如暫存檔操作與中間訊息的傳送;protected 動作可以也必須被撤銷或重做,例如一般的資料庫與訊息操作;real 動作一旦做了就無法撤銷,例如提交本身,以及操作提款機與飛機襟翼。每個交易只有兩種結局:committed 或 aborted。已提交交易的所有 protected 與 real 動作即使發生故障也必須存續,而中止交易的效果則永遠不會被其他交易看見。

time-domain addressing:版本、區間與 commit record

實體 E 持有一組值 Vi,每個值在一段半開時間區間內有效,例如 V0 有效於 T0 到 T1、V1 有效於 T1 到 T2、V2 從 T2 起是當前值。執行時間為 T3 的交易讀取 E 時,拿到的是 T3 當下有效的值,同時也會把該版本的有效區間延伸到 T3——這正是「讀取即寫入」的由來。執行時間 T3 的交易若寫入 V3,就開啟一段從 T3 起算的新區間;但若該物件當前區間的起點已經大於或等於 T3,這個交易就會被中止,因為它試圖竄改歷史。交易的所有寫入都相依於一筆 commit record:提交時系統把該記錄的狀態設為 commit 並廣播結果,使所有更新生效;中止時則以同樣方式讓它們全部失效。Reed 用 pseudo-time 而非真實時間,以迴避實作全域時鐘的困難,完整提案裡還自帶一套巢狀交易機制。

日誌記錄格式與 DO-UNDO-REDO 協定

每個可撤銷的動作除了執行本身,還必須留下一筆 undo 日誌記錄讓它能被撤銷;每個可重做的動作則必須留下 redo 日誌記錄。一筆資料庫日誌記錄包含交易名稱、同一交易的前一筆與下一筆日誌記錄指標、時間、操作型別、操作對象,以及舊值與新值。舊值新值可以是物件的完整副本,但通常只編碼變動的部分,所以更新某筆記錄的某個欄位時,記的是檔案、記錄與欄位名稱加上該欄位的新舊值,而不是整筆記錄。同一交易的日誌記錄彼此串接成鏈,撤銷時就沿著鏈往回走;同一套機制既服務程式主動發出的 abort,也用來在死結或硬體故障後清理未完成的交易。這些記錄必須放在穩定儲存(stable storage)上,通常是數個故障模式獨立的非揮發裝置;同時應該定期為每個物件留下穩定副本,好讓當前狀態能由舊狀態加上 redo 日誌重建。

延後的 real 動作與可重啟的 undo/redo

因為 real 動作無法撤銷,它就不能在結果確定之前發生,所以必須延後:這類動作一開始只產生 redo 日誌記錄,等到交易成功提交,復原系統才拿這份延後日誌把動作第一次真正做出來。這些延後動作會被命名(例如用序號),以便丟掉重複執行。另一方面,undo 與 redo 自己也必須是可重啟的:對一個已經被撤銷或已經被重做的物件再套用一次,不能破壞或改變它,因為故障也可能發生在復原處理的過程中。實作方式是替磁碟頁面標上版本號、替虛擬電路或 session 標上序號:操作先讀這個號碼,若已經是目標號碼就什麼都不做,否則才同時轉換物件與號碼。

跨多份日誌的 two-phase commit

提交是透過把 commit record 寫進日誌來宣告的,但如果一個交易寫進了多份日誌——分散式系統通常每個節點一份以上——就必須確保 commit 要嘛出現在所有日誌裡、要嘛一份都不出現。最簡單的做法是只讓交易的主動節點決定提交或中止,其他參與者都是從屬,看主動節點臉色。不過一般還是希望每個參與者在提交前都能單方面中止,而 two-phase commit 的用意正是把「不得單方面中止」的時間窗壓到最短:協調者先要求每個參與者 prepare,參與者一旦回答同意,就交出了單方面中止的權利。若全體同意,協調者廣播 commit;只要沒有取得一致同意,交易就中止。Gray 的類比是婚禮:牧師問「你願意嗎」,當事人回答「我願意」或拒絕,之後牧師才宣布結為連理,或宣布這樁婚事告吹。

鎖定:動態算出輸入與輸出集合

需求先被抽象地陳述:交易有輸入集合 I 與輸出集合 O,其他交易可以讀 I,但不得讀或寫 O;此外輸入還必須被穩定住,讓重讀同一筆記錄不會得到兩個不同答案。事先猜出 I 與 O、在排程時做交集判斷的做法,IMS/360 最早嘗試並被反覆重新發明,但一直不太成功,IMS 在 1973 年放棄了這種 intent scheduling。比較簡單也比較有效率的做法是存取物件時才對它上鎖,藉此動態計算出 I 與 O,並用兩種鎖模式區分讀與更新:讀鎖彼此相容,更新鎖則否。粒度問題的解法是挑一組固定的述詞、把它們組織成有向無環圖,然後由根往葉逐層上鎖,在任意述詞鎖的通用性與其昂貴代價之間取得折衷。至於死結,必須靠逾時或在等待關係圖中找環來偵測,選出犧牲者、用日誌把它們撤銷,並釋放其持有的鎖。

巢狀交易、save point 與沉睡中的交易

巢狀交易執行完畢後,會以副作用形式回傳自己的補償交易名稱與參數;父交易把它記在自己的日誌裡,並在父交易被撤銷時據以呼叫。Gray 特別強調這份日誌必須是使用者可見的,也就是要放進資料庫,讓使用者與應用程式知道已經做了什麼、還有什麼該做或該撤銷;他也半開玩笑地說,真的走投無路時,補償交易至少可以發一則訊息給人類:「救命,我處理不了這個。」對長時間交易,他主張接受較低的一致性程度,讓只有正在更新的交易持鎖、沉睡中的交易完全不持鎖;代價是未提交的更新會被別人看見,因此一個交易的 UNDO 與 REDO 必須能與其他交易的 DO 交換次序。若日誌記的是差量(delta)而非新舊值,加減法這類操作就能滿足交換律,這正是 IMS Fast Path 用來降低鎖競爭的手法。最後,save point 讓進行中的交易能跨越系統重啟:交易宣告一個 save point,重啟時程式與資料被重設到最近的那個點,而不是被整個丟棄。

論文證明了什麼 — 量測數據與證明

  • 磁碟雙工的可靠度算術:一顆磁碟大約一年壞一次,修好或換備品約需一小時,因此若一對鏡像磁碟獨立故障,整對同時不可用約每三千年一次,較貼近現實的分析則給出 800 年的平均故障間隔;於是一個有八對磁碟的系統大約每世紀才會出現一次整對不可用,而不做鏡像的話同樣的系統每年會有約八次磁碟不可用。
  • 以 fail-fast 反駁蠻力冗餘:Von Neumann 那套扁平的多數表決方案需要用 20,000 條線換 1 條線,因為鏈上任一故障就斷掉整條鏈;而階層式組成的電腦系統通常不到 100 個自我檢查模組,平均故障間隔以月計,因此只需要非常有限的冗餘,再配上讓平均修復時間縮到數秒或數分鐘的備品,就能得到以世紀計的系統平均故障間隔。
  • 商用系統的現場數據:Tandem NonStop 系統的平均故障間隔通常介於一到十年,而殘餘的故障來自操作員錯誤(約每年一次)與應用程式錯誤(每年數次),也就是說廠商供應的硬體與軟體已經不再是可靠度的瓶頸。
  • 交易系統無法從設計上消除的失敗:即使系統其餘部分都完美,仍有至少每 100 筆交易 1 筆會因資料輸入或授權錯誤而失敗(引自日本可靠商用系統教學論文集),這正是為什麼 abort 必須是廉價的常態操作,而不是例外處理。
  • 並行控制的統計數字:等待其實很罕見,約每 1000 筆交易才 1 筆,死結更是罕見到像奇蹟;但每秒死結數隨多工程度的平方、以及交易大小的四次方成長,這就是本文對長時間交易提出警告的量化基礎。
  • 被外推的規模基準:當時最大的航空公司與銀行約有 10,000 台終端機,任一瞬間約有 100 筆活躍交易,每筆只活一兩秒;而旅遊、保險、政府與電子郵件類應用將產生數以千計、持續數日甚至數週的並行交易。

限制與取捨 — 論文自承的,以及後來被發現的

  • 本文自己列出 time-domain addressing 的四個問題:讀取即寫入,因為讀取會推進物件的時鐘並更新其表頭,增加 I/O;等待變成中止,因為衝突時被中止的是寫入者而非讓它等待,這可能讓長時間執行的批次交易無法運作;時戳強制單一粒度,讀一百萬筆記錄就要更新一百萬個時戳,而鎖階層本可同時支援整檔與單筆記錄的鎖定;以及真實裝置上的 real 操作發生在某個真實時間,如何與 pseudo-time 對應並不清楚。Gray 承認前三項都是效能問題,實作者很可能有辦法解決。
  • 本文自承其巢狀交易並不真的是交易:別人看得見它尚未提交的更新,而這些更新之後可能被補償撤銷,所以它保有一致轉換、保有「提交或補償」的紀律、也照用 BEGIN、COMMIT、ABORT 三個動詞,卻直接放棄了 atomicity。
  • 本文自承長時間交易的解法建立在一個未經證明的推廣之上。接受較低的一致性程度,要求 UNDO 與 REDO 能與其他交易的 DO 交換次序;當日誌記的是加減這類操作的差量時這行得通,IMS Fast Path 正是這樣做的,但 Gray 直白寫道:沒有人知道這個技巧能推廣到多遠。
  • 本文對程式語言整合的提案自承高度不確定:Gray 說他不確定這個想法在一般情況下能否成立,懷疑交易概念是否真的能推廣到資料處理以外的程式領域,並警告日誌的效能代價可能高到無法承受。他最後甚至用 Peter Principle 來自嘲這個題目。
  • 後續研究補上了本文缺的部分。這裡從未把 isolation 列為獨立性質,儘管其機制實際上就在強制它;Haerder 與 Reuter 在 1983 年補上 I 並提出 ACID。two-phase commit 被當成多份日誌的答案端出來,卻沒有正面處理協調者在 prepare 之後故障所造成的阻塞問題,這個缺口後來才由 three-phase commit 與建立在 Paxos 上的共識式提交補上。而以補償為基礎的巢狀機制無法恢復可序列化性,這點在 Garcia-Molina 與 Salem 於 1987 年形式化 saga 時被講得非常明白。

它後來變成什麼 — 繼承這個想法的系統

這篇論文是交易從口耳相傳的手藝,變成一個有明確性質清單的具名抽象的關鍵時刻;兩年後 Haerder 與 Reuter 補上 isolation,把 Gray 的三性質變成 ACID,而 Gray 與 Reuter 在 1993 年的《Transaction Processing: Concepts and Techniques》基本上就是把本文的綱領完整執行一遍。以交易為單位串接日誌記錄的 DO-UNDO-REDO 協定、用頁面版本號達成可重啟性、以及把 real 動作延後到提交,全都是 ARIES 的直系祖先——ARIES 的 log sequence number 正是版本號技巧的一般化——並經由 ARIES 流入 DB2、SQL Server、PostgreSQL、MySQL InnoDB,以及今天幾乎所有採用 WAL 的儲存引擎。文中對 two-phase commit 的描述成了分散式提交的標準教材版本,後來被標準化為 X/Open XA,至今仍是 Spanner 這類系統跨分片提交的模型,而 Spanner 在底下疊上 Paxos,正是為了修掉 Gray 沒有處理的協調者阻塞問題。Gray 轉述自 Reed 在 MIT 的 time-domain addressing,則是 MVCC 與 snapshot isolation 在 PostgreSQL、Oracle、InnoDB 中的源頭,也是 Spanner、Datomic、Delta Lake、Apache Iceberg 時間旅行查詢的源頭,印證了他「日誌與版本只是同一個結構的兩個側面」的判斷。他對巢狀交易的草圖後來由 Moss 形式化,並被 Liskov 團隊實作進 Argus,也就是他文中提到正在進行的那份工作。最經久不衰的則是長時間交易那一節:補償交易、save point 與刻意降低的一致性,正是 saga 的起源,也是微服務架構、Temporal 這類編排引擎與商業流程引擎在數十年後重新發現的補償式工作流模式。

論文原文 — 逐字引用

“交易是一次狀態轉換,它具有原子性(全有或全無)、持久性(效果能存活於故障之後)與一致性(一次正確的轉換)等性質。”

摘要

“先預覽這兩種技術:日誌法把所有物件的當前狀態聚在一起,把舊版本流放到一個叫做日誌的歷史檔案裡;時間域定址則把每個物件的完整歷史(所有版本)與該物件聚在一起。”

NonStop:讓故障變罕見

“這個例子清楚說明了:動作在下一個抽象層次上可能就是交易。”

巢狀交易

術語 — 依本篇論文的用法

Transaction(交易)
一組共同構成系統狀態一致轉換的動作,且具備原子性與持久性:要嘛所有動作都完成而交易提交,要嘛所有效果都不留存而交易中止。Gray 用 consistency、atomicity、durability 三個性質來定義它,全文從未使用 isolation 這個詞。
Real action(真實動作)
一旦做了就無法撤銷的動作,例如提交本身、吐鈔、或移動飛機襟翼。real 動作必須延後到提交才執行,因此一開始只產生 redo 日誌記錄,等提交決定確立後才由復原系統據以第一次真正執行。
Compensating transaction(補償交易)
在事後另外執行、用來反轉或調整某個已提交交易效果的交易,因為已提交的交易不可撤銷。Gray 的靈感來自契約法,也來自複式簿記:發現錯誤時是加註並補上一筆沖銷分錄,而不是去塗改帳簿。
Fail-fast module(快速失效模組)
會自我檢查的元件,要嘛正確運作,要嘛偵測到自身故障後什麼都不做,絕不默默做錯事。因為系統是由不到約 100 個這種平均故障間隔以月計的模組階層式組成,把它們雙工再配上快速備品,就能得到以世紀計的系統平均故障間隔。
Time-domain addressing(時間域定址)
一種實作風格:物件從不被更新,只被「演進」,位址是名稱加上時間,每個實體持有一串帶有效區間的值。也稱為 version-oriented system;Gray 認為稱之為 immutable object system 並不恰當,因為物件的值確實會隨時間改變。
DO-UNDO-REDO 協定
規定執行一個 protected 動作時,除了做動作本身,還必須產出足以撤銷它與重做它的日誌記錄,而 unprotected 動作與純讀取則不必產生任何記錄。撤銷時沿著該交易串接的日誌記錄往回走;重做則把已提交的動作往前重放到一份舊的穩定副本上,以重建遺失的狀態。
Restartability(可重啟性)
指對一個已經被撤銷或已經被重做的物件再套用一次 UNDO 或 REDO,該物件不會被改變;之所以必要,是因為故障也可能發生在復原處理本身進行的當下。實作上是替磁碟頁面標版本號、替 session 標序號,號碼已符合就直接跳過該操作。
Two-phase commit(兩階段提交)
一種提交協定:協調者先要求每個參與者 prepare,回答同意的參與者就交出單方面中止的權利;若全體同意,協調者廣播 commit,否則交易中止。它的目的是把節點不被允許單方面中止的那段時間壓到最短。
Save point(保存點)
交易宣告的中間狀態,出事時程式與資料可以被重設到這裡,而不必整個中止。Gray 提出 save point 是為了讓進行中的長時間交易能跨越系統重啟,因為重啟時丟掉 100 筆交易只是令人不快,丟掉 10,000 筆則完全無法想像。

在時間軸上的位置 — 這篇論文在整段故事中的座標

在時間軸上查看