國產數據庫與Oracle數據庫事務差異分析

數據庫中的ACID是事務的基本特性,而在Oracle等數據庫遷移到國產數據庫國產中,可能因為不同數據庫事務處理機制的不同,在遷移后的業務邏輯處理上存在差異。本文簡要介紹了事務的ACID屬性、事務的隔離級別、回滾機制和超時機制,并總結SAVEPOINT的使用,以總結。


1、數據庫中事務基本概念

事務是數據庫中的基本邏輯操作單元,由一組不可分割的數據庫操作序列組成,這些操作要么全部成功執行,要么全部失敗回滾。其核心目的是確保數據的完整性和一致性,尤其在并發操作或系統故障時維護數據庫的可靠狀態。

1.1 事務基本屬性

ACID是事務的基本特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)。

  • 原子性:事務中的所有操作必須作為一個整體執行,要么全部執行成功、要么全部失敗回滾,不允許出現部分成功的情況。在數據庫中通常是通過日志記錄(如undo log)來實現回滾操作,若事務執行失敗,系統跟進日志撤銷已執行的操作。
  • 一致性:事務執行前后,數據庫必須保持一致性狀態。所有數據必須滿足預定義的完整性約束(如主鍵、外鍵、唯一性約束等)。即使事務失敗,數據庫也不能破壞這些規則。在數據庫中通過一些約束和檢查來確保數據庫的完整性約束。
  • 隔離性:多個事務并發執行時,每個事務的操作應與其他事務相互隔離,使得每個事務感覺不到其他事務的存在,最終效果應與事務串行執行的結果一致。數據庫中通過鎖機制(Locking)或多版本并發控制(MVCC)實現,不同的隔離級別提供不同程度的隔離性。
  • 持久性:事務一旦提交,其對數據庫的修改就是永久性的,即使系統發生故障(如斷電、崩潰),修改也不會丟失。數據庫中通過重做日志(Redo Log)實現持久性。提交事務時,對數據的修改首先寫入日志,再異步寫入數據庫文件中。當數據庫崩潰恢復時,通過重放日志恢復數據。

以轉賬交易為例,通過undo日志實現原子性,確保“扣款”和“存款”兩個操作要么全部成功,要么全部失敗;一致性是確保轉賬前后,數據庫必須滿足業務規則(如余額不為負、總額不變);通過鎖機制和MVCC多版本并發控制來實現事務的隔離性,多個并發轉賬操作互不干擾,結果與串行執行一致;持久性則是一旦轉賬成功,即使系統崩潰,修改也不會丟失。

BEGIN TRANSACTION;
-- 1. 檢查一致性:用戶A余額是否足夠(一致性)
SELECT balance FROM accounts WHERE user = 'A' FOR UPDATE;
-- 如果余額 < 100,拋出錯誤并回滾
-- 2. 扣款(原子性)
UPDATE accounts SET balance = balance - 100 WHERE user = 'A';
-- 3. 存款(原子性)
UPDATE accounts SET balance = balance + 100 WHERE user = 'B';
-- 4. 提交(持久性)
COMMIT;
1.2 事務隔離級別

事務隔離級別是數據庫事務處理的基礎,SQL-92標準定義了4種隔離級別:讀未提交(READ UNCOMMITTED)、讀已提交(READ COMMITTED)、可重復讀(REPEATABLE READ)、串行化(SERIALIZABLE)。詳見下表:

在這里插入圖片描述

不同的隔離級別有不同的現象,并有不同的鎖和并發機制。隔離級別越高,數據庫的并發性能就越差。

1.2.1 臟讀/不可重復讀/幻讀現象

1)臟讀
A事務讀取B事務尚未提交的更改數據,并在這個數據的基礎上進行操作,這時候如果事務B回滾,那么A事務讀到的數據是不被承認的。

在這里插入圖片描述

2)不可重復讀
不可重復讀是指在同一個事務中,同一個查詢在T1時刻讀取一行數據,在T2時刻重新讀取這一行數據的時候,發現這一行數據已經發生了修改(被更新或者刪除)。假如A在取款事務的過程中,B往該賬戶轉賬100,A兩次讀取的余額發生不一致。

3)幻讀
幻讀是指在同一個事務中,當同一個查詢多次執行的時候,由于其它插入操作的事務提交,會導致每次返回不同的結果集。不可重復讀和幻讀的區別是:前者是指讀到了已經提交的事務的更改數據(修改或刪除),后者是指讀到了其他已經提交事務的新增數據。

在這里插入圖片描述

1.2.2 行鎖模式
  • Share:lock owner和任何并發程序可以read但是不能change locked page或row,并發程序可能獲得S-lock、U-lock,也可能沒有lock就進行讀操作
  • Update:lock owner可read但是不能change locked page或row,但是owner可以將U-lock升級為X-lock這樣就可以修改page或row
    • 升級為X-lock這個過程可能會引起其它S-lock的并發進程暫停在那
    • 當lock owner讀數據的時候并決定是否需要修改它的時候,U-lock會減少deadlocks的幾率
  • Exclusive:只有lock owner才能read或change locked page或row,并發程序只有當程序處于UNCOMMITTED read isolation的時候才能訪問數據
  • Lock mode compatibility,見下表

在這里插入圖片描述

比如說User A對page hold住S-lock,如果User B想對page請求X-lock,則User A的lockmode會拒絕User B的請求。

1.2.3 隔離級別

1)讀未提交(Read Uncommitted)
讀未提交,就是一個事務可以讀取另一個未提交事務的數據,也稱為臟讀。在讀數據時候不加鎖,寫數據時候加行級別的共享鎖,提交時釋放鎖。行級別的共享鎖,不會對讀產生影響,但是可以防止兩個同時的寫操作

2)讀已提交隔離級別(Read Committed)
讀提交,就是一個事務要等另一個事務提交后才能讀取它的數據,否則是讀取不到另外一個事務的更改的數據。
事務讀取數據(讀到數據的時候)加行級共享S鎖,讀完釋放;事務寫數據時候(寫操作發生的瞬間)加行級獨占X鎖,事務結束釋放。由于事務寫操作加上獨占X鎖,因此事務寫操作時,讀操作也不能進行,因此,不能讀到事務的未提交數據,避免了臟讀的問題。但是由于,讀操作的鎖加在讀上面,而不是加在事務之上,所以,在同一事務的兩次讀操作之間可以插入其他事務的寫操作,所以可能發生不可重復讀的問題。

3)可重復讀隔離級別(Repeatable Read)
當事務隔離級別為可重復讀時,只能讀到該事務啟動時已經提交的其他事務修改的數據,未提交的數據或在事務啟動后其他事務提交的數據是不可見的。對于本事務而言,事務語句可以看到之前的語句做出的修改。
事務讀取數據在讀操作開始的瞬間就加上行級共享S鎖,而且在事務結束的時候才釋放。但是,由于加的是行級別的鎖,仍然可能發生幻讀的問題。

4)序列化(Serialization)
最嚴格的隔離級別,強制事務串行執行,使之不可能沖突,從而解決幻讀的問題,資源消耗最大。在讀操作時,加表級共享鎖,事務結束時釋放;寫操作時候,加表級獨占鎖,事務結束時釋放。在這個級別,可能會導致大量的鎖超時和鎖競爭現象,實際上也很少用到。

1.2.4 不同數據庫隔離級別

不同數據庫支持的隔離級別也不同

在這里插入圖片描述

  • Oracle數據庫支持讀已提交和序列化,默認隔離級別為Read Committed,通過通過多版本并發控制(MVCC)避免臟讀,但存在不可重復讀和幻讀。
  • MySQL數據庫支持四種隔離級別,默認為可重復讀,通過MVCC和間隙鎖來減少幻讀問題。
  • MySQL數據庫支持四種隔離級別,默認為Read Committed
  • OceanBase(for Oracle)模式支持讀已提交和序列化,默認為Read Committed
  • TiDB支持讀已提交、可重復讀和序列化,默認為Repeatable Read,其實在TiDB中實現是快照隔離,類似可重復讀;
  • GoldenDB兼容MySQL的隔離機制,支持4種隔離級別,但是默認的級別是Read Committed,也是并發和一致性平衡的結果;
  • GaussDB支持Read Committed和Repeatable Read,默認隔離級別是Read Committed
1.3 事務回滾機制

事務的原子性要求事務要么全部執行成功、要么全部執行失敗回滾,但是對于Oracle數據庫支持語句級的原子性,也就是一個事務中單個語句執行失敗,則只會回滾該語句執行的操作,不會導致在當前事務中丟失之前的任何工作。如果需要回滾整個事務,需要處理錯誤并且主動調用ROLLBACK。這種語句級的回滾對于處理一些長時間運行的批處理任務有用,邏輯上希望能夠處理錯誤,不需要回滾已經完成的所有操作。

在這里插入圖片描述

不過從Oracle數據庫遷移到國產數據庫中,大部分數據庫在事務的回滾機制上并不支持語句級別的,因此需要通過采用SAVEPOINT保存點的方式。使用savepoint雖然可以解決語句級別功能上的需求,但是不合理的使用可能引發其它問題。

1.4 事務超時機制

數據庫中事務會設置不同的超時機制,防止因為出現等鎖而出現無限等待,超過這個時間后會出現等鎖超時,事務會回滾。

在這里插入圖片描述

  • 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表示不控制。
1.5 如何使用SAVEPOINT

前文提到Oracle數據庫中支持語句級別的回滾,在遷移到國產數據庫后,為了兼容Oracle數據庫這個特性,很多數據庫支持savepoint機制。SAVEPOINT 是事務中的一個邏輯標記點,用于標識事務執行到某個特定位置的狀態。通過ROLLBACK TO SAVEPOINT可以回滾到該標記點,撤銷該點之后的所有操作,但保留該點之前的操作。SAVEPOINT可以提供細粒度的事務控制,避免因整個事務回滾導致的數據丟失。對于一些復雜或長時間運行的事務中,可以分階段提交或回滾操作。

BEGININSERT INTO orders (id, amount) VALUES (1, 100);SAVEPOINT sp1;  -- 設置保存點sp1UPDATE inventory SET stock = stock - 1 WHERE product_id = 101;SAVEPOINT sp2;  -- 設置保存點sp2-- 假設此處發生錯誤ROLLBACK TO sp1;  -- 回滾到sp1,撤銷UPDATE操作COMMIT;           -- 提交事務(僅保留INSERT操作)
END;

但是在一個長事務中不規范的使用SAVEPOINT可能會導致實例內存上漲、事務執行時間異常的問題。比如在Oracle數據庫中的一個游標查詢語句,每1K筆執行一次,遷移到GaussDB之后,URL串中指定了autosave參數,這樣在每次游標訪問時候都會執行一次SAVEPOINT動作,原來幾分鐘的任務可能幾個小時都執行不完,出現很多SAVEPOINT等待事件,并且數據庫實例的內存逐漸上漲。

那么對于一些復雜的業務場景,如何合理的使用SAVEPOINT?

  • 禁止自動設置SAVEPOINT,只在必要時設置SAVEPOINT,如在數據更新、復雜邏輯分支操作上設置;
  • 將長事務拆分為多個小事務,每處理一定的數據后提交,以釋放資源;
  • 避免在游標循環中頻繁執行SAVEPOINT,改用批量處理或分頁查詢;
  • 及時回滾或釋放無用SAVEPOINT,在邏輯分支完成后,主動回滾到最近的SAVEPOINT并釋放資源;
  • 避免嵌套過深的SAVEPOINT:過多的嵌套SAVEPOINT會增加回滾段的復雜度。

參考資料:

  1. https://pigsty.cc/blog/db/oracle-pg-xact/
  2. TiDB中的事務處理機制

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79115.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79115.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79115.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dockerfile 學習指南和簡單實戰

引言 Dockerfile 是一種用于定義 Docker 鏡像構建步驟的文本文件。它通過一系列指令描述了如何一步步構建一個鏡像&#xff0c;包括安裝依賴、設置環境變量、復制文件等。在現實生活中&#xff0c;Dockerfile 的主要用途是幫助開發者快速、一致地構建和部署應用。它確保了應用…

青少年編程與數學 02-016 Python數據結構與算法 22課題、并行算法

青少年編程與數學 02-016 Python數據結構與算法 22課題、并行算法 一、GPU并行計算矩陣乘法示例 二、MPI并行計算allgather操作示例 三、Python中的并行計算多線程并行計算多進程并行計算 四、SIMD并行計算SIMD并行計算示例 總結 課題摘要: 并行算法是通過同時執行多個任務或操…

20250412 機器學習ML -(3)數據降維(scikitlearn)

1. 背景 數學小白一枚&#xff0c;看推理過程需要很多時間。好在有大神們源碼和DS幫忙&#xff0c;教程里的推理過程才能勉強拼湊一二。 * 留意&#xff1a; 推導過程中X都是向量組表達: shape(feature, sample_n); 和numpy中的默認矩陣正好相反。 2. PCA / KPCA PCAKPCA(Li…

宿舍管理系統(servlet+jsp)

宿舍管理系統(servletjsp) 宿舍管理系統是一個用于管理學生宿舍信息的平臺&#xff0c;支持超級管理員、教師端和學生端三種用戶角色登錄。系統功能包括宿舍管理員管理、學生管理、宿舍樓管理、缺勤記錄、添加宿舍房間、心理咨詢留言板、修改密碼和退出系統等模塊。宿舍管理員…

現代測試自動化框架教程:Behave接口測試與Airtest移動端UI自動化

前言 我發現每天還是陸陸續續有人在看我之前寫的自動化框架搭建的文檔&#xff1b;即使很早就有新的框架&#xff0c;更好的選擇出來了&#xff1b;所以特別寫了這一篇目前大廠也在使用的&#xff1b;日活400w有實際落地的自動化測試架構方案&#xff1b; 隨著測試技術…

.NET Core DI(依賴注入)的生命周期及應用場景

在.NET中&#xff0c;依賴注入&#xff08;DI&#xff0c;Dependency Injection&#xff09;是一種設計模式&#xff0c;它通過將依賴關系注入到類中&#xff0c;而不是讓類自己創建依賴項&#xff0c;來降低類之間的耦合度。這使得代碼更加模塊化、靈活和易于測試。在.NET中&a…

設計模式 --- 觀察者模式

觀察者模式是一種行為設計模式&#xff0c;它定義了對象之間的一對多依賴關系&#xff0c;當一個對象的狀態發生改變時&#xff0c;所有依賴它的對象都會得到通知并自動更新。 優點&#xff1a; ??1.解耦性強??&#xff1a; ??觀察者&#xff08;訂閱者&#xff09;與主…

PasteForm框架開發之Entity多級嵌套的表單的實現

你相信么,使用PasteForm框架開發&#xff0c;管理端居然不要寫代碼&#xff01;&#xff01;&#xff01; 一起來看看PasteForm是否支持多級表模式(外表) 需求假設 假如有這么一個需求&#xff0c;就是訂單表&#xff0c;包含了多級的信息&#xff0c;比如這個訂單包含了哪些…

深入解析分類模型評估指標:ROC曲線、AUC值、F1分數與分類報告

標題&#xff1a;深入解析分類模型評估指標&#xff1a;ROC曲線、AUC值、F1分數與分類報告 摘要&#xff1a; 在機器學習中&#xff0c;評估分類模型的性能是至關重要的一步。本文詳細介紹了四個核心評估指標&#xff1a;ROC曲線、AUC值、F1分數和分類報告。通過對比這些指標…

多模態醫學AI框架Pathomic Fusion,整合了組織病理學與基因組的特征

小羅碎碎念 在醫學AI領域&#xff0c;癌癥的精準診斷與預后預測一直是關鍵研究方向。 這篇文章提出了Pathomic Fusion這一創新框架&#xff0c;致力于解決現有方法的局限。 傳統上&#xff0c;癌癥診斷依賴組織學與基因組數據&#xff0c;但組織學分析主觀易變&#xff0c;基因…

《Python星球日記》第27天:Seaborn 可視化

名人說&#xff1a;路漫漫其修遠兮&#xff0c;吾將上下而求索。—— 屈原《離騷》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 專欄&#xff1a;《Python星球日記》&#xff0c;限時特價訂閱中ing 目錄 一、Seabor…

【scikit-learn基礎】--『監督學習』之 決策樹回歸

決策樹算法是一種既可以用于分類&#xff0c;也可以用于回歸的算法。 決策樹回歸是通過對輸入特征的不斷劃分來建立一棵決策樹&#xff0c;每一步劃分都基于當前數據集的最優劃分特征。 它的目標是最小化總體誤差或最大化預測精度&#xff0c;其構建通常采用自上而下的貪心搜索…

解決安卓開發“No Android devices detected.”問題

解決安卓開發“No Android devices detected.”問題 ? 當我們插入移動設備的USB時&#xff0c;卻發現這并未顯示已連接到的設備 點擊右側的Assistant,根據提示打開移動設備開發者模式并啟用USB調試模式,然后發現我們未連接到移動設備的原因是ABD服務的原因 問題確定了&…

idea如何使用git

在 IntelliJ IDEA 中使用 Git 的詳細步驟如下&#xff0c;分為配置、基礎操作和高級功能&#xff0c;適合新手快速上手&#xff1a; ?一、配置 Git? ?安裝 Git? 下載并安裝 Git&#xff0c;安裝時勾選“Add to PATH”。驗證安裝&#xff1a;終端輸入 git --version 顯示版本…

軟件架構設計:MVC、MVP、MVVM、RIA 四大風格優劣剖析

MVC、MVP、MVVM 和 RIA 都是軟件架構中常見的設計風格&#xff0c;以下是對它們的詳細介紹&#xff1a; 一、MVC 架構風格&#xff08;Model - View - Controller&#xff09; 1.簡介&#xff1a;MVC 架構風格將軟件應用程序分為三個核心部分&#xff0c;通過這種劃分來分離不…

Centos/RedHat 7.x服務器掛載ISCSI存儲示例(無多路徑非LVM)

客戶讓幫忙掛載個ISCSI存儲&#xff0c;大概結構如下圖所示&#xff1a; ISCSI存儲為一臺安裝了truenas的X86服務器&#xff0c;提供存儲服務的IP地址為10.16.0.1 服務器的ETH1網卡配置與10.16.0.1同段網絡。 為了給客戶做個簡單培訓&#xff0c;整理了一下操作步驟。下面是配…

TV板卡維修技術【二】

【一】測量未知MOS引腳定義的好壞 TO-252封裝的MOS管子&#xff0c;上面的大焊盤是D極&#xff0c;下面的3個不同品牌的NMOS或者PMOS驗證了這個結論&#xff1a; 利用這個特性&#xff0c;可以在不知道MOS引腳定義的情況下測量出MOS的好壞&#xff0c;如下圖&#xff1a; 插件…

基于 cefpython 實現嵌入 Chromium (CEF)

CEF Python是一個開源項目&#xff0c;旨在為Chromium Embedded Framework提供Python綁定&#xff0c;許多流行的GUI工具包都提供了嵌入CEF瀏覽器&#xff0c;例如QT。 安裝 pip install cefpython366.1支持的Python版本&#xff1a; 實現打開網頁 from cefpython3 import…

MySQL-存儲引擎和索引

1.MySQL的基礎架構是什么&#xff1f; MySQL由連接器、分析器、優化器、執行器和存儲引擎這五部分構成。 一條SQL的執行流程&#xff1a; 通過連接器連接數據庫&#xff0c;檢查用戶名和密碼&#xff0c;以及權限校驗&#xff0c;是否有增刪改查的權限。在MySQL8.0之前&#…

安卓性能調優之-掉幀測試

掉幀指的是某一幀沒有在規定時間內完成渲染&#xff0c;導致 UI 畫面不流暢&#xff0c;產生視覺上的卡頓、跳幀現象。 Android目標幀率&#xff1a; 一般情況下&#xff0c;Android設備的屏幕刷新率是60Hz&#xff0c;即每秒需要渲染60幀&#xff08;Frame Per Second, FPS&a…