您是否曾遇過「SQL0946C The transaction log for the database is full」這個令人頭痛的錯誤訊息?在忙著解決問題時,是否曾停下腳步思考:交易日誌究竟為何而存在?日誌記錄服務的核心目的又是什麼?
若無交易機制,多使用者與應用程式同時存取資料庫時,資料損壞將不可避免;而若無交易日誌記錄,DB2 UDB 中的多種資料庫恢復方法將無從存在。別擔心若您尚未完全掌握這些概念——本文將為您詳細拆解什麼是交易、交易日誌記錄背後的運作機制,並示範如何在系統崩潰或程式故障後,利用資料庫交易日誌檔案中儲存的資訊,將資料庫帶回一致且可用的狀態。更重要的是,這些關鍵日誌的用途遠不止於此;在未來的專欄中,我將展示如何利用交易日誌檔案重演操作,將資料庫精確恢復到任意指定時間點的狀態。
交易,亦稱為工作單元,是指一個或多個 SQL 操作的序列,這些操作組合成一個不可分割的單元,通常位於一個應用程式處理序內。之所以稱之為「原子」,是因為它不可再分——要麼全做,要麼全不做。一個交易可包含任意數量的 SQL 操作(從一個到數千個),視業務邏輯中對「一步」的定義而定。
交易的開始與終止定義了資料庫中資料一致性的界點:要么將交易中所有操作的結果應用到資料庫並使之永久生效(已提交),要么全部撤銷(回滾),讓資料庫回到啟動該交易前的狀態。
交易在建立資料庫連線後首次執行 SQL 陳述式時,或在現有交易終止時立即啟動。一旦啟動,可使用「原子提交」功能隱式終止該交易——此時每條可執行的 SQL 陳述式均被視為一個獨立交易。若陳述式執行成功,其修改即應用到資料庫;若失敗,修改則被丟棄。此外,也可透過執行 COMMIT 或 ROLLBACK SQL 陳述式來顯式終止交易,基本語法如下:
COMMIT [WORK]
ROLLBACK [WORK]
COMMIT 會將交易從開始起對資料庫所做的所有修改永久化;ROLLBACK 則撤銷所有修改。未提交的修改對其他使用者與應用程式不可見(除非使用未提交讀 UR 隔離級別);一旦提交,修改對所有使用者可見,且只能透過新交易中的新 SQL 陳述式來移除。
當對基本表執行 INSERT 時,記錄首先在緩衝區中建立,該緩衡區與指定該表資料儲存位置的表空間相關聯。每次更新或刪除記錄時,包含該記錄的頁面會從儲存體檢索並複製到適當的緩衝區,再由 UPDATE/DELETE 修改。修改完成後,反映該動作的記錄會被寫入日誌緩衝區——記憶體中另一指定儲存區(其大小由 logbufsiz 資料庫配置參數控制)。
INSERT:寫入包含新行資料值的記錄DELETE:寫入包含該行原始值的記錄UPDATE:寫入包含該行原始值與新值的記錄(多數情況下透過在原始值上執行 EXCLUSIVE OR 生成)當執行 INSERT、UPDATE 或 DELETE 的交易終止時,相應的 COMMIT 或 ROLLBACK 記錄會被寫入日誌緩衝區。
每當啟動緩衝區 I/O 頁面清理器、日誌緩衝區已滿、或提交/回滾交易時,日誌緩衝區中的所有記錄會立即寫入磁碟上的一或多個交易日誌檔案。若發生系統故障,日誌緩衝區的持續刷新將最小化可能遺失的日誌記錄數。一旦與特定交易相關的所有日誌記錄(含相應的 COMMIT/ROLLBACK 記錄)成功具體化為日誌檔案,交易本身的結果才會被複製到適當的表空間容器以永久儲存(已修改的資料頁仍保留在記憶體中以供快速存取,最終會被改寫)。此過程稱為「寫前日誌記錄」,確保對資料的修改在記錄到資料庫前,總是先被具體化為日誌檔案。

因多個交易可同時使用一個資料庫,單一日誌檔案可能包含屬於數個不同交易的日誌記錄。為追蹤哪條日誌記錄屬於哪個交易,每條日誌記錄會被分配一個特殊的交易 ID,綁定到建立它的交易。透過交易 ID,可隨時將特定交易相關的日誌記錄寫入一或多個日誌檔案,不影響資料一致性——最終,終止該交易的 COMMIT 或 ROLLBACK 記錄也會被記錄下來。
若在交易修改尚未提交前發生問題(如斷電、應用程式異常終止),該交易的任何未提交或已回滾工作將遺失。此外,若正在將資料具體化到資料庫的已提交交易遭破壞,資料庫將處於不一致、不可用狀態(嘗試建立連線時會產生返回代碼與錯誤訊息)。雖無法恢復記憶體中儲存的交易記錄,但可透過執行「崩潰恢復」操作,將不一致的資料庫恢復為一致、可用狀態。
啟動崩潰恢復最常用的方法是從 DB2 命令列處理器(CLP)執行 RESTART 命令,基本語法如下:
RESTART [DATABASE | DB]
[DatabaseName]
USER [UserName] [ USING [PassWord] ]
[ DROP PENDING TABLESPACES ( [TS_Name] , ... ) ]
[ WRITE RESUME ]
其中 DatabaseName 指定嘗試恢復的資料庫名稱;UserName/PassWord 指定執行崩潰恢復的使用者權限;TS_Name 指定若恢復表空間時遇錯誤則被禁用或置為 Drop Pending 模式的表空間名稱。若需在名為 SAMPLE 的資料庫上執行崩潰恢復,只需執行 RESTART DATABASE SAMPLE。
也可配置資料庫自動啟動崩潰恢復:將 AUTORESTART 配置參數設為 ON。每當啟動資料庫或嘗試建立連線時,DB2 Database Manager 會檢查資料庫狀態;若參數為 ON 且資料庫處於不一致狀態,Database Manager 會自動執行 RESTART 命令。
崩潰恢復過程中,會分析資料庫交易日誌檔案中儲存的記錄,將每個擁有相應 COMMIT 記錄的交易記錄重新應用到資料庫(重做),並撤銷所有沒有相應 COMMIT 記錄的記錄(回滾)——這就是為何所有更新操作都要記錄前後資訊的原因。因日誌記錄頻繁具體化,且特定交易的修改只有在交易成功終止時才具體化,故障後將資料庫恢復到一致性狀態的能力總能得到保證。
崩潰恢復只是交易日誌功能之一。在後續專欄中,我將展示如何利用交易日誌檔案中的記錄進行前滾恢復,將資料庫恢復到任意指定時間點的狀態——但這需要先理解備份映像與版本恢復等概念,將在下一期介紹。