日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

免费开放阅读 | 数据库管理系统的事务原理(上)

發布時間:2024/2/28 windows 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 免费开放阅读 | 数据库管理系统的事务原理(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.




作者介紹: 那海藍藍,騰訊技術工程事業群計費平臺部金融云TDSQL數據庫T4級專家,熟悉PostgreSQL、MySQL、Informix等數據庫內核技術,著有《數據庫查詢優化器的藝術》一書。《數據庫事務處理的藝術》為最新出版力作,經機械工業出版社授權,“騰訊技術工程官方號”將獨家免費開放閱讀,我們將分期為讀者奉上那海藍藍的技術盛宴。


本篇介紹數據庫管理系統的事務處理技術,從數據庫的事務理論出發界定事務處理技術的范圍,討論了事務機制應對的問題、事務處理的理論基礎和并發控制技術。


全篇立足于數據庫事務處理的基本理論,第 1 章界定了本書討論的事務處理技術所解決的問題,幫助讀者理解事務處理技術的背景和需求。在筆者看來,理解問題比掌握解決問題的方式更為重要。


第 2 章講述事務處理技術的基本概念和理論,但不是對經典教科書的翻錄,而是結合筆者多年數據庫內核開發的心得和經驗,融入自己的理解,幫助讀者從眾多的頭緒中理出線索。當然,要想徹底理解掌握事務處理的基礎理論,還需要系統、全面地閱讀經典的事務處理教材。


如果能夠把閱讀經典教材和本書相結合,并對比印證,則如步入百花叢中:百花叢中識花香,迷霧夢里尋捷徑,這是一本好書所能做到的事情。

但愿書長久,十年共嬋娟。


第 1 章?數據庫管理系統的事務原理


數據庫管理系統(DataBase? Management? System,DBMS,以下簡稱“數據庫”),是位于用戶與操作系統之間的一層數據管理軟件,功能主要包括:數據定義、數據操縱、數據庫的運行管理、數據庫的建立和維護 等 。

數據庫的事務處理機制,是數據庫技術的基石。掌握數據庫技術,必須要掌握事務處理的技術,這樣才能把握數據庫的核心技術。同時,也必須了解數據庫為什么會需要事務處理技術,即事務處理技術要解決的問題,這一點,就是我們在第一章第一節開門見山地提出的問題。

?

1.1 事務模型要解決的問題

事務模型,是電子交易操作的保障。沒有事務模型,并發操作以及操作中途的系統異常將可能使數據發生混亂,本節就各種潛在的問題進行討論。


1.1.1?????為什么需要事務處理機制

數據庫為什么需要事務處理機制?

面對這個問題,一些數據庫相關從業者掩卷思考,給出以下幾個答案:

答案一:數據庫的事務處理機制,主要是解決臟讀、不可重復讀、幻讀等問題的。答案二:數據庫的事務處理機制,主要是實現了ACID 特性的。

答案三:數據庫的事務處理機制,主要是以多版本兩階段封鎖協議實現可串行化快照隔離。引自《數據庫系統概論》王珊,薩師暄著。

?

以上答案,哪個正確呢?其實,沒有一個是正確的。


對于第一個回答,提出了事務處理技術中可能出現的三種經典問題,這三種問題,是數據庫事務處理技術中并發控制模塊為實現不同隔離級別而要解決的三個問題,不是事務處理機制面臨的問題。所以第一個回答,以局部問題來覆蓋整體,以偏概全了。


第二個回答,提出了 ACID四大特性 ,這四個特性在關系型數據庫中一個也不可少, 但這僅僅是“四個特性”,并不是我們需要數據庫事務處理機制的根本原因。


第三個回答,提出了多項事務處理機制中需要的技術,如多版本(Multiversion concurrency control,MVCC)、兩階段封鎖(2 Phase Lock)、快照隔離(Snapshot Isolation)等,但是這些技術僅僅是事務處理機制中的一些重要技術,用于并發控制管理和隔離級別的實現,并不是需要事務處理機制的原因。


那么,什么是數據庫事務模型被提出的原因呢?


我們先回避問題,繞道看如下的一個實際用戶操作,從 A 賬戶轉賬 50 元到 B 賬戶,其過程如表1-1 所示。

表 1-1 事務處理機制的作用

第一種情況,沒有事務處理機制

第二種情況 ,有事務處理機制

1. read(A)

2. A := A – 50

3.? write(A)

4.? read(B)

5. B := B + 50

6. write(B)

?begin

1. read(A)

2. A := A – 50

3.? write(A)

4.? read(B)

5. B := B + 50

6. write(B)

?commit

假設第 3 行“3. write(A) ”操作完成,A 賬戶已經少

了 50 元

假設第 3 行“3. write(A) ”操作完成,A 賬戶已經少

了 50 元

從第四行開始,數據庫宕機;重啟后,A 賬戶少了 50

元但是 B 賬戶卻沒有增加 50 元

從第四行開始,數據庫宕機;重啟后,事務沒有提交,

A 賬戶盡管少了 50 元,但是事務因沒有成功提交,導致 A 減少 50 元的操作“失效”

那么,A 少了的 ?50 元,哪里去了?

那么,A 少了 50 元的操作,被回滾掉了,A 不會有

經濟損失

如果發生這樣的事情,誰還敢用數據庫來記錄交易信息?

如果發生這樣的事情,A 是不是不用擔心劃賬失敗了?


事務處理機制,就是要保證用戶的數據操作動作對數據是“安全的”。


那么,什么樣的操作是安全的呢?數據只有在帶有“ ACID ”四個特性的事務處理機制的保障下,才可以認為是“安全的”。


這里提到的大家耳熟能詳的“ ACID”四個特性,正是事務模型的核心內容。事務概念及其相關技術(為實現“ACID”四個特性的技術)的提出,給應用開發人員抽象出一個非常好用的數據處理模型,這個模型可以保證:操作間串行執行,執行中不必擔心出錯。這


ACID,A是原子性,C是一致性,I是隔離性,D是持久性。詳見1.2.1節。


就是事務模型被提出的原因。A 保證了操作(一些有完整邏輯意義的數據讀寫動作)要么成功要么失敗,A 和 C 保證了數據不會因寫操作發生不一致,I 保證了在多會話并發讀寫同一份數據的情況下數據的完全一致(或數據可能不一致但尚可接受),D 保證了被修改的數據能長久地存儲。


事務模型自被提出后,逐漸成為商業世界穩定有序運作的基石,數據和數據承載的交易事件的結果不會因系統故障被損傷。關系型數據庫管理系統實現了事務模型,使得數據庫在電子交易中發揮了非常重要的作用。這也是數據庫為什么需要事務處理機制,即事務模型的原因。


1.1.2 事務機制要處理的問題—事務故障、系統故障、介質故障

事務模型是商業世界運作的基石,主要體現在交易處理電子化。作為一個軟件系統, 數據庫系統會遭遇一些故障,如我們常說的事務故障、系統故障、介質故障等。


對于數據庫系統,因為數據實在太為重要,數據庫系統應該能夠保證在出現故障時, 數據依然滿足 ACID 特性。


對于事務內部的故障,一般可分為預期的和非預期的。預期的事務內部故障是指可以通過數據庫的事務處理機制發現的事務內部故障,這時數據庫的事務處理機制提供了回滾操作保證了數據免受損害;非預期的事務內部故障如運算溢出故障、并發事務死鎖故障、違反了某些完整性約束而導致的故障等,數據庫系統依然可以通過回滾操作保證數據免受損害,所以回滾操作在事務處理機制中占有重要地位,不同的數據系統對回滾的實現方式也不盡相同。


對于系統故障,如數據庫在運行過程中,由于硬件故障、數據庫軟件及操作系統的漏洞、突然停電等,數據庫系統停止運行,所有正在運行的事務以非正常方式終止,需要數據庫系統重新啟動,這時,數據庫系統為保障ACID 特性,提供了基于 REDO/UNDO 的恢復機制,可以正確恢復到系統崩潰前的狀態。


介質故障也稱為硬故障,主要指數據庫在運行過程中,由于磁頭碰撞、磁盤損壞、強磁干擾、天災人禍等情況,使得數據庫中的數據部分或全部丟失。解決這一類故障,要依賴于備份系統和歸檔日志,歸檔的日志、系統運行期間記載的REDO/UNDO 日志等日志相關內容,也是事務處理機制的一部分,日志管理部分的內容較多,一般的書籍會將日志管理獨立為若干章節進行討論。


總的來說,事務處理機制為應對這三類故障,提供了很多技術,如日志與恢復子系統、并發控制子系統、存儲子系統等,和事務處理機制密切相關,我們將在1.2 節繼續進行討論。


1.1.3 并發帶來的問題—三種常見的讀數據異常現象

數據不在 ACID 特性的保護下會發生不一致的現象,那么:在 ACID 的保護下,是不是數據就一定不會產生不一致的現象呢?


在關系數據庫系統中,多個會話(session)可以訪問同一個數據庫的同一個表的同一行數據。這樣,對于數據而言,就意味著在同一個時間段內,有多個會話可以對其施加操作(或讀操作或寫操作),讀寫操作施加的順序不同以及事務中 A 特性對事務結果的影響(或成功或失敗,即要么提交要么中止),這三種因素疊加在一起,會存在幾種對數據有不同影響的情況:

  • 讀– 讀操作:如果同時只存在多個讀操作,對于數據自身則沒有影響;既讀和讀操作互不影響數據的一致性,讀讀操作可以并發執行。

  • 讀 – 寫操作:如果讀寫操作都存在,因寫在前讀在后(如臟讀現象)、讀在前寫在后


(如不可重復讀現象),或者讀在前寫在后然后又讀(如幻象現象),就可能因數據被寫而導致另外一個讀操作的會話讀到錯誤的數據。這個操作可以根據動作發生的先后順序被細分為讀 – 寫操作、寫 – 讀操作。


  • 寫 – 寫操作:如果同時存在多個寫操作,寫 – 寫操作直接改變了數據在同一時刻的語義,這就更不被允許,所以寫 – 寫操作通常不允許被并發執行。但是,如果不做并發控制,寫– 寫并發操作也會帶來數據異常現象(1.1.4節探討寫 – 寫操作引發的異常)。

這三種情況的第二種,對應了 SQL 標準中定義的三種數據異常的現象,注意這三種異常都是針對某個事務(第 2.2.1 節稱這樣的事務為“主事務”)的讀操作而言的。SQL2003標準對于數據異常現象的定義如下:

The isolation level specifies the kind of phenomena that can occur during the execution of concurrent SQL-transactions. The following phenomena are possible:
1) P1 (“Dirty read”): SQL-transaction T1 modifiesa row. SQL-transaction T2 then read sthat row before T1 performs a COMMIT. If T1 then performs a ROLLBACK, T2 will have read a row that was never committed and that may thus be considered to have never existed.
2) P2 (“Non-repeatable read”): SQL-transaction T1 readsa row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified valueor discover that the row has been deleted.
3) P3 (“Phantom”): SQL-transaction T1 reads the set of rows N that satisfy some <search condition>. SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the <search con-dition> used by SQL-transaction T1. If SQL-transaction T1 then repeats the initial read with the same <search condition>, it obtains a different collection of rows.


怎么理解上面的內容呢?從 SQL 標準的定義可以看出:

?首先,涉及了并發事務(concurrentSQL-transactions):至少有兩個事務同時發生,如上面所舉的三種異常現象中,分別使用了事務T1和 T2。但是,更為復雜的情況,如下一節所談到的“寫偏序(writeskew)”現象的發生可以是兩個或三個事務同時發生。


其次,涉及了隔離級別(isolation level):如果多個事務是“可串行化”的,則意味著事務之間不應該互相影響(不是“一定互不影響”而是“不應該互相影響”),即邏輯上不應當存在“讀寫”沖突,所以數據庫引擎實現時應該避免“讀寫”沖突造成的數據不一致的現象。避免的含義就是在數據庫引擎編碼實現的時候,采取并發控制技術,消除“臟讀”、“不可重復讀”、“幻象”這三種現象。采取的手段是分級控制(不同的隔離級別),分別使用“已提交? (READCOMMITTED)”、“可重復讀(REPEATABLE? READ)”和“可串行化(SERIALIZABLE)”這幾種隔離級別,來應對這三種數據不一致的現象。


數據操作的對象,臟讀和不可重復讀是以“row”(一行)為單位,而幻象現象操作的是一個數據集(零行到多行)。


下面,我們把 SQL 標準的話語轉為一個表格(如表 1-2 所示),以更好地理解一下三種異常現象。

表 1-2 SQL 標準定義的三種讀數據異常現象


說明:

  • 表格頭兩行,表明? SQL? 標準定義的三種異常現象,分別是臟讀、不可重復讀、幻象。

  • 表格第一列,時間值列,表明時間值在逐漸增長,即 t0<t1<t2<t3。

  • 對于每一種異常現象,都分為2個列,分別是兩個并發的事務,各自命名為 T1事務和 T2事務。

  • 表格中的 R(row),表示讀 row數據對象;W(row) 表示寫 row對象,讀寫操作的是同一個數據對象 row;W(row)-Update/Delete后面的 Update/Delete表示的寫操作是DML語句中的 UPDATE或 DELETE語句產生的寫數據庫對象 row的操作。

  • 帶有“ R(rows)-WHERE<condition> ”的表示SQL語句讀數據(通常是 SELECT語句)帶有 WHERE子句,此子句的條件表達式是“<condition> ”。

  • 帶有“ W(rows)-Update/Insert-<condition>”的表示寫操作生成的數據滿足與其他事務讀操作帶有的相同的條件表達式“<condition> ”,且此寫操作要么是UPDATE,要么是 INSERT語句。

  • 帶有底色的,表示其對應時刻,如果發生對應的操作,將引發異常現象。

  • 臟讀現象:按照時間順序,T1事務在 t0時刻對 row進行了修改(更新),T2事務在 t1時刻先讀取了被 T1修改了的 row的值,但是 T1在 t2時刻中止使得對row的修改失效。如果數據庫引擎不支持因并發操作避免數據異常,則 T2在 t1 時刻讀到的就是 T1修改后的數據,但是這個數據在現實世界中不存在,對于事務 T2而言,讀取了被回滾掉的數據,即事務 T2發生了臟讀異常現象。另外 , 對于臟讀現象 , 還存在如表 1-3的兩種變形情況。

  • 不可重復讀現象:事務 T1在 t0時刻先讀取 row的舊值,事務 T2在 t1時刻對 row進行了修改(更新或刪除)然后提交事務使得修改生效,此時row因更新變為了新值或因刪除而不再存在。接下來,事務 T1在 t3時刻再次讀取 row對象的值但是 row的值已經是新值或者不存在了。對于事務 T1 而言,物是(同樣是讀 row這個對象)人非(值已經和 t0時刻讀到的值不同),事務 T1發生了不可重復讀異常現象。

  • 幻象現象:事務 T1在 t0時刻帶有特定條件地讀取了row對象的數據,事務 T2在 t1 時刻插入新的數據或更新其他舊數據但滿足事務T1的特定 WHERE 條件,新的數據滿足與事務 T1同樣的條件,當事務 T1在t3時刻再次以同樣的條件讀取數據的時候,rows 對象的值已經有新加入的行(因插入而比第一次讀多出了數據)。對于事務 T1而言,物是(同樣是讀滿足“<condition> ”條件的多個 row對象)人非(值已經和 t0時刻讀到的值不同),事務 T1發生了幻象異常現象。幻象又稱為幻讀,即第二次讀操作讀取了第一次讀操作沒有讀到的rows(一行或多行)。


臟讀異常的變形如表 1-3 所示。

表 1-3?? 臟讀異常的變形


在了解了 SQL 標準定義的三種異常現象后,回到我們在本節開始提出的問題:

在 ACID 的保護下,是不是數據就一定不會產生不一致的現象呢?

答 案 已 經 很 明確: 即 使 數 據 庫 系 統 提 供 ACID, 除 非 我 們 使 用“可 串 行 化


(SERIALIZABLE)”隔離級別,否則數據在其他不同的隔離級別下還會產生數據不一致的現象。

有關這三種數據異常現象的更多探討,請參見 1.1.7 節。


1.1.4 并發帶來的問題—寫 – 寫并發操作引發的數據異常現象

上一節,我們探討了三種讀數據異常現象,請注意,異常現象發生在一個事務中后面的READ 讀操作上。這三種讀數據異常現象被 SQL 標準定義。那么:是不是對數據的并發操作只會產生上述的三種讀數據異常現象?


事務概念的奠基人,Jim Grey 先生,在其著作《事務處理:概念與技術》中提到了一個“Lost Update ”異常的概念,字面含義是“更新丟失”,這是一個寫操作的異常,與上一節提到的三種讀操作異常不同。

除了“ Lost Update ”異常外,這一節我們還將探討另外一種異常,如表 1-4所示。

表 1-4?? 寫數據異常現象


說明:

  • 表格頭兩行,表明寫寫并發操作引發的兩種異常現象,分別是臟寫、丟失更新。

  • 表格第一列,時間值列,表明時間值在逐漸增長,即 t0<t1<t2<t3。

  • 對于每一種異常現象,都分為2個列,分別是兩個并發的事務,各自命名為 T1事務和 T2事務。

  • 表格中的 R(row),表示讀 row數據對象;W(row) 表示寫 row對象,讀寫操作的是同一個數據對象 row;W(row)-Update后面的 Update表示的寫操作是 DML語句中的UPDATE語句產生的寫數據庫對象 row的操作。

  • 帶有陰影背景的,表示其對應時刻,如果發生對應的操作,將引發異常現象。

  • 臟寫現象:按照時間順序,事務 T1在 t0時刻對 row進行了修改(更新),事務 T2在 t1時刻對 row進行了修改(更新),如果沒有并發控制,T2對 row的修改會生成新值,但是 T1在 t3時刻回滾使得 T2對 row的修改失效,而 T1的語義是:T1 自身對 row的修改失效這就把 T2修改的值回滾掉。對于事務 T1而言,回滾掉了不是自己修改的數據,即事務 T1上發生了臟寫現象。

  • 丟失更新現象:按照時間順序,事務 T2在 t1時刻對 row進行了修改(更新),事務


T1在 t2時刻對 row進行了修改(更新),如果沒有并發控制,T1對 row的修改會生成新值,但是 T1在 t3時刻提交使得 T2對 row的修改失效。對于事務 T1而言,覆蓋掉了不是自己修改的數據,即事務 T1上引發了丟失更新現象(t3時刻如果是事務

T2提交而不是事務T1提交,也是丟失更新,只是事務T2上引發了丟失更新現象)。不管是讀異常還是寫異常,并發控制技術都要規避這些異常,保證數據在不同隔離級別下一致性不被破壞。


1.1.5 語義約束引發的數據異常現象

如果說數據在 ACID 特性(帶有了并發控制技術)的保護下會發生不一致的現象,那么:在 ACID 和快照隔離級別技術(多版本)的保護下,是不是數據就一定不再會產生不一致的現象呢?


答案是否定的。數據庫系統中數據的異常,在多種并發控制技術中已經被解決,但這不表明所有的異常都已經被解決,更不表明不再有新的異常被發現。


我們知道,數據庫并發控制技術中有一個大名鼎鼎的技術,稱為快照隔離(Snapshot Isolation) ,這項技術解決了讀和寫之間的沖突,在保證數據不會產生前面兩節提到的讀異常和寫異常的情況下,使得讀寫互不阻塞(兩階段封鎖技術中讀寫操作互相阻塞),提高了并發度。


注意我們這里談到的多版本是“multi-version,簡稱 MV ”,其相對于“single-valued,簡稱 SV”,這個多版本是指并發控制技術中的數據項有多個版本,其含義僅此而已。快照隔離并發技術是多版本并發控制(Multiversion concurrency control,MVCC)技術的一部分, 其發生作用,需基于“數據項存在多個版本”。


快照隔離并發控制技術的缺點,是并不能真正保證事務為“可串行化的”,即事務間的并發操作依舊會引發數據異常現象,但是這里的數據異常現象有別于前面提到的各種異常現象,其異常現象是“業務的邏輯語義”引發的,即除了抽象的讀寫操作,數據間還應該滿足一定語義,即約束(constraint)。


在快照隔離并發控制技術中并發的事務因不滿足約束而發生的異常,稱為“寫偏序(Write Skew)”,這樣的異常有兩種,參見表 1-5。

說明:

  • 表格頭兩行,表明寫偏序異常現象的兩種情況,分別是由兩個事務引發異常、三個事務引發異常。

  • 表格第一列,時間值列,表明時間值在逐漸增長,即 t0<t1<t2<t3<t4<t5<t6<t7。

  • 對于每一種異常現象,都分為2個列,分別是兩個并發的事務,各自命名為 T1事務和 T2事務。

? ?詳情參見2.1.2節。

表 1-5 寫偏序異常的兩種情況


二個事務引發的異常現象(簡單寫偏序,Simple Write Skew):按照時間順序,T1 事務在t0時刻讀取了在打電話的值班醫生個數,T2事務在 t1時刻也讀取了在打電話的值班醫生個數。事務 T1在 t2時刻進行判斷:如果在打電話的值班醫生個數大于等于2?人則請Alice停止打電話。事務 T2在 t3時刻進行判斷:如果在打電話的值班醫生個數大于等于 2人則請 Bob停止打電話。然后事務 T1和 T2分別提交。如果在這種并發的情況下,允許事務T1和 T2都提交成功,則 t6時刻,Alice和 Bob都停止了打電話。如果串行執行事務,先執行事務 T1后執行事務 T2,Alice會停止打電話但 Bob不會停止,這與前一種情況的結果不同;如果先執行事務 T2后執行事務 T1,Bob會停止打電話但 Alice不會停止,這與前一種情況的結果也不同;這表明前一種并發執行是非序列化的,而此時,事務 T1、T2并發時違反了約束(約束為:如果同時打電話的人數大于等于2人則請 Alice或 Bob其中一個人停止打電話直到同時打電話的人數少于 2人) 發生了寫偏序異常現象。對于簡單寫偏序,可以用一個形象化的圖表示,如圖 1-1 所示。


圖 1-1 兩個事務引發的異常現象優先圖

? ?示例源自論文:DanR.K. Ports,KevinGrittner,SerializableSnapshotIsolationinPostgreSQL


三個事務引發的異常現象(Batch Processing):對于這種情況,后兩個并發更新事務T3 和 T2 是可串行化的且不存在任何異常,但是一個只讀事務 T1 出現在某個時刻卻可能正好造成問題。所出現的問題是這樣的,當事務 T3 提交時,T2 處于活躍狀態, 這時,事務 T1 啟動要讀取事務 T2 和 T3 涉及的數據(current_batch 和 receipts),這時,事務 T1 的快照包括了事務T3 的插入后的結果(因為 T3 已經提交);但是,事務 T2 沒有提交,它的插入操作數據不包含在事務 T1 的快照中。在優先圖(如圖 1-2 所示)中會造成一個環(有關如何形成這樣的環,參見 2.2.5 節),說明這樣的調度是非可串行化的。

圖 1-2 三個事務引發的異常現象優先圖



本節所述的這兩種情況,如果使用優先圖表示,都可以在參與操作的事務之間,畫出一個環,存在環說明:調度是非可串行化的。為解決這樣的問題,要求數據庫引擎必須在事務提交時(甚至是環一形成即立刻回滾其中的一個事務)而不是在快照上檢查完整性約束,以避免本節所述的不一致現象。


1.1.6其他的異常

在《A Critique of ANSI SQL Isolation Levels》這篇論文中,除了上面提到的幾種異常現象外,還提到了另外兩種異常,如表 1-6 和表 1-7 所示。

表 1-6? 讀 偏 序

? ?圖1-1、圖1-2的具體含義,請參見2.2.5節。?


說明:

  • 表格頭兩行,表明讀偏序異常現象,是由兩個事務引發異常。

  • 表格第一列,時間值列,表明時間值在逐漸增長,即 t0<t1<t2<t3。

  • 對于讀偏序異常現象,都分為2個列,分別是兩個并發的事務,各自命名為 T1事務和 T2事務。

  • 事務 T1在 t0時刻讀出數據 x,事務 T2在 t1時刻對數據 x和 y進行了修改在 t2時刻提交,事務 T1在 t3時刻讀取 y,y是被事務 T2修改后的數據,此時已經不是 t0 時刻事務 T1讀取 x時對應的 y值,數據形成了不一致狀態(注意此時不是數據x處于不一致,而是 y處于不一致)。


游標(Cursor),是數據庫引擎提供的一種讀取數據的方式。在數據庫中,為了防止使用游標時其他事務并發修改游標所包括的數據,定義了游標穩定性(Cursor Stability)隔離級別,這樣的隔離級別,是在讀取當前數據項的時刻,在數據項上加鎖,當游標從當前數據項移走則解鎖,此后曾經被讀取過的數據項不再被并發保護(盡管使用游標的事務沒有提交或中止,還處于活動狀態)。但是,在使用游標的時候,也會發生寫 – 寫異常,如表 1-7所示。

表 1-7?? 游標丟失更新


說明:

  • 表格頭兩行,表明寫 – 寫并發操作引發的異常現象,游標丟失更新。

  • 表格第一列,時間值列,表明時間值在逐漸增長,即 t0<t1<t2<t3。

  • 對于每一種異常現象,都分為2個列,分別是兩個并發的事務,各自命名為 T1事務和 T2事務。

  • 游標丟失更新現象:按照時間順序,事務 T1在 t0時刻讀取 row的值后,即釋放了

row 上的鎖使得 row 沒有被并發保護,事務 T2 在 t1 時刻對 row 進行了修改(更新),事務 T1 在 t2 時刻對 row 進行了修改(更新),如果沒有并發控制,T1 對 row 的修改會生成新值,但是T1 在 t4 時刻提交使得 T2 對 row 的修改失效。對于事務 T1 而言, 覆蓋掉了不是自己修改的數據,即事務 T1 上引發了丟失更新現象。這樣的現象,本質上就是丟失更新,只是發生在了游標上,所以稱為游標丟失更新。


我們在 1.1.3 至 1.1.6 節,介紹了各種因并發引發的異常現象,有多種技術(2.2 節介紹多種并發控制技術)可以解決這些異常現象,如下我們借用《A Critique of ANSI SQL Isolation Levels》這篇論文中的一張表,來簡單總結一下前面幾節所談到的各種異常,如表1-8?所示。與隔離級別相關的內容,參見 2.1節。

表1-8 所有的異常和隔離級別的關系


說明:

  • P0 DirtyWrite:臟寫,1.1.4節表 1-3。

  • P1 DirtyRead:臟讀,1.1.3節表 1-2。

  • P4 CCursorLostUpdate:游標丟失更新,1.1.6節表 1-6。

  • P4 LostUpdate:丟失更新,1.1.3節表 1-2。

  • P2 FuzzyRead:模糊讀,即不一致讀,1.1.3節表 1-2。

  • P3 Phantom:幻象,即幻讀,1.1.3節表 1-2。

  • A5A ReadSkew:讀偏序,1.1.6節表 1-5。

  • A5B WriteSkew:寫偏序,1.1.5節表 1-4。

  • 與隔離級別相關的內容,參見 2.1節。

  • 深入探討三種讀數據異常現象


在 1.1.3 節,我們提出了并發帶來的三種異常現象,分別是臟讀、不可重復讀、幻象, 其中幻象又被稱為“幻讀”。


這一節,我們將以問答的形式,深入探討與這三種異常現象相關的六個問題。


Q1:異常現象是發生在表 1-2 中的事務 T1 還是事務 T2 ?

換一個提問方式,我們都知道數據庫提供了四種隔離級別,那么當三種異常發生的時候,是應該在事務T1 中還是事務 T2 中設置隔離級別以避免數據異常現象的產生?


答:首先,需要區分操作發生的主體。數據庫啟動多個會話,要想會話之間互不影響,則需要標識哪個是當前會話、哪個是其他會話,然后設置隔離級別。有人認為,這個很簡單,每個會話對于其自身就是當前會話。但是,對于數據庫引擎而言,他是不知道哪個會話是當前的會話。


其次,需要考慮并發度。對于數據庫引擎而言,如果因為數據庫引擎不知道哪個會話是當前的會話,所以給每個會話的事務都設置不同的隔離級別,減少各個會話的事務互相影響,則會降低并發度。


所以,在數據庫保留一個默認的隔離級別(通常是較低的隔離級別以提高并發度)給每個會話的事務后,如果需要高的隔離級別,就需要在自己的事務中設置想要的隔離級別,以使得本事務不受其他事務的影響。因此,在數據庫系統中,我們要想使得事務 T1不受其他事務的影響,則需要在事務 T1內部設置隔離級別,使得本事務 T1不受其他并發事務對事務 T1要讀寫的數據造成影響。換句話說,就是使得本事務不發生異常現象。回看表1-2 以及對表 1-2的說明,我們可以看到如下內容:

  • 臟讀現象:……事務 T2發生了臟讀異常現象。

  • 不可重復讀現象:……事務 T1發生了不可重復讀異常現象。

  • 幻象現象:……事務 T1發生了幻象異常現象。


這個結論看起來有點兒不“美”,即有點不協調,臟讀是發生在了事務 T2,不可重復讀和幻象是發生在了事務T1。


如果數據異常都發生在事務 T1,則我們可以把事務T1 想象成為“本事務”,事務 T2是其他并發的事務,而我們當前可以操作的(即有權限可以設置隔離級別)只能是“本事務”,其他并發發生的事務也許是其他權限用戶建立的會話,我們根本沒有權限操作即沒有權限去設置他人的隔離級別。


所以,數據異常現象,一定是發生在本事務當中的。我們統一以事務 T1 為本事務(也稱為“主事務”),觀察本事務和其他并發事務之間因讀寫操作的先后次序不同而造成的不同的數據異常。因此,我們修正表 1-2 的內容如表1-9 所示。

表 1-9 修正后的SQL 標準定義的三種讀數據異常現象

? “W(rows)-Update/Insert? =><condition>”表示更新和插入操作的行滿足“<condition>”。


對于 Q1 問題的回答,依據表 1-9,數據異常現象發生在表 1-9 中的主事務 T1 中。其實,如上修改是為了明確并發事務的數據異常現象發生在哪里。即研究別的事務對于本事務的影響,而不是討論本事務對別的事務的影響。


對于數據庫引擎的編碼實現,就是在一個會話中考慮本會話(主事務對應的會話)因不同的隔離級別(在主事務中設置的隔離級別)在發生沖突后而產生什么樣的動作(可繼續執行本事務內的后續 SQL 還是直接回滾掉本事務)。所以,請注意,動作發生的主體,一定是主事務。而且,異常是發生在主事務的讀操作這樣的動作上(指三種讀異常)。


Q2 :從表 1-9 中看,對于臟讀現象,寫操作是事務T2 執行 UPDATE 引發的,那么, 事務 T2 的寫操作可以是刪除(DELETE)或插入(INSERT)嗎?

答:臟讀,強調的是主事務讀取了一個不存在(因回滾而不存在)的數據。

如果事務 T2的寫操作是刪除操作,在 row這行數據被刪除后,事務 T1不可能在后面的時間點 t1上讀到同一個 row(SQL標準中特意強調了“thatrow”,參見 1.1.3節);因此臟讀現象中“事務 T1一定可以讀到同一個 row”是不能滿足的,因此,臟讀中的事務T2 的寫操作不可能是刪除。


如果事務 T2 的寫操作是插入操作,在row 這行數據被插入后,事務 T1 能在后面的時間點上讀到同一個 row(SQL 標準中特意強調了“ that? row ”);因此臟讀現象中事務 T1 一定可以讀到同一個 row 的條件是被滿足的,因此,臟讀中的事務T2 的寫操作可以是插入。


Q3:對于不可重復讀現象,事務 T2 的寫操作是否可以是插入操作?

答:對于事務 T2 的 W(row) 操作,row 是一個已經存在的行,這表明是在一個存在的特定對象上進行的操作,所以不可能是插入操作。


Q4:不可重復讀和幻象有什么區別?

答:首先,這兩種異常,對于主事務 T1 而言,都是先讀取了數據,之后因事務 T2“寫” 了數據而事務 T1 再次讀取數據的時候,發生了異常。但是,如表1-9 所示,不可重復讀對于事務 T1 讀取的是一個存在的確定的一行數據(意味著這行數據是存在的數據),這個行數據本身被事務 T2 使用更新或刪除操作而改變;而幻象對于事務 T1 讀取的是滿足條件“ <condition> ”的多行數據(意味著“<condition> ”是一個范圍查找,結果集不確定),所以從第一次讀取數據的操作的角度看,前者是讀取特定的多行,后者讀取的是多行但可能 不確定。不過,對于所讀的數據而言,由此可以產生一個新的問題,參見Q5。其次,這兩種異常,對于事務 T2 而言,都是“寫”數據,但是寫操作的具體動作不同。如表 1-9 所示,不可重復讀對于事務 T2 的寫操作是更新或刪除操作,而幻象對于事務 T2 的寫操作是插入(插入的新數據滿足條件)或更新(使不滿足條件的數據在更新后滿足條件)操作。


第三,不可重復讀和幻象最大的區別就是前者只需要“鎖住”(考慮)已經讀過的數據,而幻象需要對“還不存在的數據”做出預防。


Q5:對于幻象現象,事務 T2 的寫操作是否可以是更新操作或者刪除操作?

答:對于幻象現象中事務 T2 的 W(rows) 操作,如果操作是一個更新或刪除操作,則表明這樣的操作等同于(相似但不完全一樣,區別參見 Q6)不可重復讀(即是在多個行數據上進行更新或刪除,即在多個行數據上批量化重演了不可重復讀現象)。


如表 1-10 所示,比較不可重復讀和幻象現象。如果我們認為幻象現象中的事務T2 可以是更新或刪除操作,則幻象就等同于不可重復讀。實際上,幻象是不可重復讀的一個特例,對于不可重復讀現象,可以擴展其“ R(row)/W(row) ”的概念為“ R(rows)/W(rows) ” 即讀寫多行(實則是擴展 1.1.3 節 SQL 標準提出的不可重復讀的定義),即對多行的不可重復讀。只是 ANSI SQL 標準著眼于在單行上定義不可重復讀,本節擴展的定義著眼于在多行上重復單行上定義的不可重復讀(而編碼實現的實踐中,數據庫引擎是對多行數據使用相同的方式進行處理的)。

表 1-10 幻象的寫操作改為更新則等同于不可重復讀


另外,幻象異常現象中的操作都帶有“<condition> ”,而不可重復讀現象中則沒有“<condition> ”, 這 可 以 把 不 可 重 復 讀 變 形 為 類 似“R(rows)-WHERE<true> ”, 即 “ <condition> ”相當于“ <true> ”。但是, 幻象的定義, 強調的是在特定的行(元組) 被操作后,又有新的行被其他事務操作而產生,所以,我們可以重新校正表 1-9得到新的表1-11,發生變化的內容使用深色背景表示,幻象現象中事務T2的操作是插入或更新。


從表 1-11 可以看出,不可重復讀現象中事務 T2 著眼于對現有數據進行操作;而幻象現象中事務T2 著眼于對新增(或不在鎖定范圍內已經存在的數據上做更新 / 插入后而得的數據滿足了謂詞條件)數據。這其實正是Q4 的答案。


Q6:表 1-11中,不可重復讀現象中的事務 T2在 t2時刻執行“ Commit”或不執行“Commit”會有什么差別嗎?或者對于幻象現象,事務T2在 t2時刻沒有執行“Commit”,這一點與不可重復讀有差別嗎?

答:對于這個問題,我們暫時不做回答,請讀者先行思考。在我們討論了并發控制相關的多種技術后,我們在 2.2.6 節再深入探討這個問題。

表 1-11 第二次修正后的 SQL 標準定義的三種讀數據異常現象


總結

以上是生活随笔為你收集整理的免费开放阅读 | 数据库管理系统的事务原理(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。