數據庫中的ACID是事務的基本特性,而在Oracle等數據庫遷移到國產數據庫國產中,可能因為不同數據庫事務處理機制的不同,在遷移后的業務邏輯處理上存在差異。本文簡要介紹了事務的ACID屬性、事務的隔離級別、回滾機制和超時機制,并總結SAVEPOINT的使用,以總結。
1、數據庫中事務基本概念
事務是數據庫中的基本邏輯操作單元,由一組不可分割的數據庫操作序列組成,這些操作要么全部成功執行,要么全部失敗回滾。其核心目的是確保數據的完整性和一致性,尤其在并發操作或系統故障時維護數據庫的可靠狀態。
1.1 事務基本屬性
ACID是事務的基本特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)。
原子性:事務中的所有操作必須作為一個整體執行,要么全部執行成功、要么全部失敗回滾,不允許出現部分成功的情況。在數據庫中通常是通過日志記錄(如undo log)來實現回滾操作,若事務執行失敗,系統跟進日志撤銷已執行的操作。
一致性:事務執行前后,數據庫必須保持一致性狀態。所有數據必須滿足預定義的完整性約束(如主鍵、外鍵、唯一性約束等)。即使事務失敗,數據庫也不能破壞這些規則。在數據庫中通過一些約束和檢查來確保數據庫的完整性約束。
隔離性:多個事務并發執行時,每個事務的操作應與其他事務相互隔離,使得每個事務感覺不到其他事務的存在,最終效果應與事務串行執行的結果一致。數據庫中通過鎖機制(Locking)或多版本并發控制(MVCC)實現,不同的隔離級別提供不同程度的隔離性。
持久性:事務一旦提交,其對數據庫的修改就是永久性的,即使系統發生故障(如斷電、崩潰),修改也不會丟失。數據庫中通過重做日志(Redo Log)實現持久性。提交事務時,對數據的修改首先寫入日志,再異步寫入數據庫文件中。當數據庫崩潰恢復時,通過重放日志恢復數據。
以轉賬交易為例,通過undo日志實現原子性,確保“扣款”和“存款”兩個操作要么全部成功,要么全部失敗;一致性是確保轉賬前后,數據庫必須滿足業務規則(如余額不為負、總額不變);通過鎖機制和MVCC多版本并發控制來實現事務的隔離性,多個并發轉賬操作互不干擾,結果與串行執行一致;持久性則是一旦轉賬成功,即使系統崩潰,修改也不會丟失。
1.2 事務回滾機制
事務的原子性要求事務要么全部執行成功、要么全部執行失敗回滾,但是對于Oracle數據庫支持語句級的原子性,也就是一個事務中單個語句執行失敗,則只會回滾該語句執行的操作,不會導致在當前事務中丟失之前的任何工作。如果需要回滾整個事務,需要處理錯誤并且主動調用ROLLBACK。這種語句級的回滾對于處理一些長時間運行的批處理任務有用,邏輯上希望能夠處理錯誤,不需要回滾已經完成的所有操作。
1.3 事務超時機制
數據庫中事務會設置不同的超時機制,防止因為出現等鎖而出現無限等待,超過這個時間后會出現等鎖超時,事務會回滾。
Oracle數據庫:默認不會主動終止因行鎖等待而阻塞的事務,事務會無限期等待鎖釋放,需由應用層處理或手動終止,行鎖在事務提交或回滾是自動釋放;事務默認也無超時設置,但是可以限制會話的空閑時間,超過時間后會斷開鏈接。
MySQL數據庫:通過 innodb_lock_wait_timeout 控制,默認為50秒。當事務等待鎖超過此時間時,會拋出錯誤;事務中無默認超時時間,但是連接的空閑超時設置wait_timeout,默認8小時。
PostgreSQL:通過pg_lock_timeout設置行鎖等待超時時間,默認為0無限等待;事務中設置statement_timeout 控制單條SQL執行時間,默認無限制。
TiDB:兼容MySQL行鎖等待設置;如果是悲觀事務,默認TTL(Time-To-Live)為 1小時,超時后自動回滾,另外通過tidb_idle_transaction_timeout 控制空閑事務。
OceanBase:MySQL模式下兼容MySQL設置;事務中通過 ob_query_timeout 控制事務單條語句執行時間,默認1800s
GoldenDB:兼容MySQL設置
GaussDB:參數lockwait_timeout控制單個鎖的最長等待時間,當申請的鎖等待時間超過設定值時,系統會報錯,默認為20min;通過通過 statement_timeout 控制單個語句執行時長,默認0表示不控制。