偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

國產(chǎn)數(shù)據(jù)庫與Oracle數(shù)據(jù)庫事務差異分析

數(shù)據(jù)庫 Oracle
數(shù)據(jù)庫中的ACID是事務的基本特性,而在Oracle等數(shù)據(jù)庫遷移到國產(chǎn)數(shù)據(jù)庫國產(chǎn)中,可能因為不同數(shù)據(jù)庫事務處理機制的不同,在遷移后的業(yè)務邏輯處理上存在差異。

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

1、數(shù)據(jù)庫中事務基本概念

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

1.1 事務基本屬性

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

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

以轉賬交易為例,通過undo日志實現(xiàn)原子性,確?!翱劭睢焙汀按婵睢眱蓚€操作要么全部成功,要么全部失?。灰恢滦允谴_保轉賬前后,數(shù)據(jù)庫必須滿足業(yè)務規(guī)則(如余額不為負、總額不變);通過鎖機制和MVCC多版本并發(fā)控制來實現(xiàn)事務的隔離性,多個并發(fā)轉賬操作互不干擾,結果與串行執(zhí)行一致;持久性則是一旦轉賬成功,即使系統(tǒng)崩潰,修改也不會丟失。

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 事務隔離級別

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

圖片

不同的隔離級別有不同的現(xiàn)象,并有不同的鎖和并發(fā)機制。隔離級別越高,數(shù)據(jù)庫的并發(fā)性能就越差。

1.2.1 臟讀/不可重復讀/幻讀現(xiàn)象

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

圖片

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

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

圖片

1.2.2 行鎖模式
  • Share:lock owner和任何并發(fā)程序可以read但是不能change locked page或row,并發(fā)程序可能獲得S-lock、U-lock,也可能沒有l(wèi)ock就進行讀操作
  • Update:lock owner可read但是不能change locked page或row,但是owner可以將U-lock升級為X-lock這樣就可以修改page或row
  • 升級為X-lock這個過程可能會引起其它S-lock的并發(fā)進程暫停在那
  • 當lock owner讀數(shù)據(jù)的時候并決定是否需要修改它的時候,U-lock會減少deadlocks的幾率
  • Exclusive:只有l(wèi)ock owner才能read或change locked page或row,并發(fā)程序只有當程序處于UNCOMMITTED read isolation的時候才能訪問數(shù)據(jù)
  • 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)讀未提交,就是一個事務可以讀取另一個未提交事務的數(shù)據(jù),也稱為臟讀。在讀數(shù)據(jù)時候不加鎖,寫數(shù)據(jù)時候加行級別的共享鎖,提交時釋放鎖。行級別的共享鎖,不會對讀產(chǎn)生影響,但是可以防止兩個同時的寫操作

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

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

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

1.2.4 不同數(shù)據(jù)庫隔離級別

不同數(shù)據(jù)庫支持的隔離級別也不同

圖片圖片

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

1.3 事務回滾機制

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

圖片圖片

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

1.4 事務超時機制

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

圖片圖片

  • Oracle數(shù)據(jù)庫:默認不會主動終止因行鎖等待而阻塞的事務,事務會無限期等待鎖釋放,需由應用層處理或手動終止,行鎖在事務提交或回滾是自動釋放;事務默認也無超時設置,但是可以限制會話的空閑時間,超過時間后會斷開鏈接。
  • MySQL數(shù)據(jù)庫:通過 innodb_lock_wait_timeout 控制,默認為50秒。當事務等待鎖超過此時間時,會拋出錯誤;事務中無默認超時時間,但是連接的空閑超時設置wait_timeout,默認8小時。
  • PostgreSQL:通過pg_lock_timeout設置行鎖等待超時時間,默認為0無限等待;事務中設置statement_timeout 控制單條SQL執(zhí)行時間,默認無限制。
  • TiDB:兼容MySQL行鎖等待設置;如果是悲觀事務,默認TTL(Time-To-Live)為 1小時,超時后自動回滾,另外通過tidb_idle_transaction_timeout 控制空閑事務。
  • OceanBase:MySQL模式下兼容MySQL設置;事務中通過 ob_query_timeout 控制事務單條語句執(zhí)行時間,默認1800s
  • GoldenDB:兼容MySQL設置
  • GaussDB:參數(shù)lockwait_timeout控制單個鎖的最長等待時間,當申請的鎖等待時間超過設定值時,系統(tǒng)會報錯,默認為20min;通過通過 statement_timeout 控制單個語句執(zhí)行時長,默認0表示不控制。

1.5 如何使用SAVEPOINT

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

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

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

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

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

參考資料:

  1. https://pigsty.cc/blog/db/oracle-pg-xact/
  2. TiDB中的事務處理機制
責任編輯:武曉燕 來源: 牧羊人的方向
相關推薦

2011-11-04 14:07:40

存儲

2011-08-12 13:33:31

Oracle數(shù)據(jù)庫自治事務

2009-11-20 13:29:59

Oracle數(shù)據(jù)庫恢復

2011-08-23 15:16:54

OracleMySQL

2023-01-05 08:45:07

國產(chǎn)數(shù)據(jù)庫代碼

2011-03-11 09:14:18

國產(chǎn)數(shù)據(jù)庫

2011-03-11 09:26:13

2010-04-15 08:57:29

Oracle數(shù)據(jù)庫

2011-08-10 15:46:29

數(shù)據(jù)庫

2011-03-16 08:54:45

Oracle數(shù)據(jù)庫索引

2011-03-10 13:24:26

2010-04-23 09:23:44

Oracle 數(shù)據(jù)庫

2011-05-26 10:30:12

Oracle數(shù)據(jù)庫約束

2015-08-21 12:59:38

Oracle數(shù)據(jù)庫

2010-05-05 14:44:50

Oracle數(shù)據(jù)庫

2012-03-16 09:29:47

國產(chǎn)數(shù)據(jù)庫

2011-04-01 13:21:26

SQL ServerOracle數(shù)據(jù)庫查詢優(yōu)化

2009-09-24 14:12:22

Hibernate數(shù)據(jù)

2010-10-08 09:38:55

Android數(shù)據(jù)庫事

2009-04-03 10:54:49

Oracle備份恢復
點贊
收藏

51CTO技術棧公眾號