oracle事務隔離機制
交易隔離等級:一個事務對資料庫的修改 與 另一個與之並行的事務 的隔離程度。
兩個並發事務同時訪問資料庫表相同的行時,可能存在以下三個問題:
1、幻想讀:事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,恰好滿足T1的where條件。然後T1使用相同的條件重新查詢,結果集中可以看到T2插入的記錄,這條新紀錄就是幻想。
2、不可重複讀取:事務T1讀取一行記錄,緊接著事務T2修改了T1剛剛讀取的記錄,然後T1重新查詢,發現與第一次讀取的記錄不同,這稱為不可重複讀取。
3、髒讀:事務T1更新了一行記錄,還未提交所做的修改,這個T2讀取了更新後的資料,然後T1執行復原操作,取消剛才的修改,所以T2所讀取的行就無效,也就是髒資料。
為了處理這些問題,SQL標準定義了以下幾種交易隔離等級:
READ UNCOMMITTED 幻想讀、不可重複讀取和髒讀都允許。 ------------------都允許
READ COMMITTED 允許幻想讀、不可重複讀取,不允許髒讀
REPEATABLE READ 允許幻想讀,不允許不可重複讀取和髒讀
SERIALIZABLE 幻想讀、不可重複讀取和髒讀都不允許 -----------------都不允許
Oracle資料庫支援READ COMMITTED 和 SERIALIZABLE這兩種交易隔離等級。所以Oracle不支援髒讀
SQL標準所定義的預設交易隔離等級是SERIALIZABLE,但是Oracle 預設使用的是READ COMMITTED
設定隔離等級使用 SET TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
下面是oracle 設定SERIALIZABLE隔離等級一個樣本:
左面是事務T1,右面是事務T2,因為T2層級為SERIALIZABLE,所以即使事務T1在提交了資料之後,事務T2還是看不到T1提交的資料,幻想讀和不可重複讀取都不允許了。
那如何能查看到T1新增的記錄呢? 上面T1和T2是並發執行,在T1執行insert的時候事務T2已經開始了,因為T2層級是SERIALIZABLE,所以T2所查詢的資料集是T2事務開始前資料庫的資料。即事務T1在事務T2開始之後的insert和update操作的影響都不會影響事務T2。現在重新開啟一個事務T3 就可以看到T1新增的記錄了。
當下列事件發生時,事務就開始了:
1、串連到資料庫,並執行第一條DML語句
2、前一個事務結束後,又輸入了另一條DML語句
---------------------------------------------------------------------------------------------------------------------------
13、資料一致性和並發性
這一章描述了Oracle如何維護多使用者資料庫環境中的資料一致性問題。
本章包含下列主題:
u 多使用者環境中的資料並發性和一致性介紹
u Oracle如何管理資料並發性和一致性
u Oracle如何鎖定資料
u Oracle閃回查詢概述
多使用者環境中資料並發性和一致性介紹
在單使用者資料庫中,使用者修改資料庫中的資料,不用擔心其他使用者同時修改相同的資料。但是,在多使用者資料庫中,同時執行的多個事務中的語句可以修改同一資料。同時執行的事務需要產生有意義的和一致性的結果。因而,在多使用者資料庫中,資料並發性和資料一致性的控制非常重要:
u 資料並發性:指很多使用者可以同時訪問資料
u 資料一致性:指每個使用者可以看到資料的一致性結果,包括自身事務和其他事務產生的改變。
為給同時啟動並執行事務描述一致性事務行為,Oracle研究員定義了一個交易隔離等級:串列性(serializability)。事務行為的的可串列模式試圖確保事務啟動並執行方式看起來像是一次運行一個事務(或者串列性),而不是並發運行。
雖然事務間的這種隔離等級經常使用,但這種模式下的很多應用程式會降低輸送量。並發運行事務的完全隔離意味著一個事務不能對另外一個事務正在查詢的表執行插入。簡而言之,真實環境中經常要在優秀的交易隔離等級和效能之間做一個折衷。
Oracle提供了兩個隔離等級,為應用程式開發人員提供可選的模式來兼顧效能和一致性。
可預防現象和交易隔離等級
ANSI/IOS SQL標準(SQL 92)定義了4個交易隔離等級,對交易處理效能的影響也個不相同。這些隔離等級是考慮了事務並發執行必須避免的3個現象提出的。
3個應該避免的現象為:
u 髒讀:一個事務可以讀取其他事務寫入但還沒有提交的資料。
u 不可重複讀取(模糊讀):一個事務重複讀到以前讀到的和查詢到的資料,這些資料是其他的已提交事務已經修改或者刪除的資料。
u 幻影讀:一個事務重複執行查詢返回的一些列行,這些行包括其他已經提交的事務已經插入的額外的行。
SQL92根據這些對象定義了4個隔離等級,事務運行在特定的隔離等級允許特別的一些表現。如表13-1所示。
表13-1 隔離等級阻止的讀現象
隔離等級 |
髒讀 |
不可重複讀取 |
幻影讀 |
非提交讀(read uncommitted) |
允許 |
允許 |
允許 |
提交讀(read committed) |
不允許 |
允許 |
允許 |
重複讀(Repeatable read) |
不允許 |
不允許 |
允許 |
串列性(serializable) |
不允許 |
不允許 |
不允許 |
Oracle提供提交讀(read commited)和串列性(serializable)隔離等級,而唯讀模式不是SQL92的一部分。提交讀是預設的。
鎖機制概述
通常來說,多使用者資料庫使用多種類型的資料鎖來解決相關資料並發、一致性和完整性的問題。鎖是防止訪問同一資源的事務的破壞性幹擾的一種機制。
資源套件括兩種通用的類型:
u 使用者物件,例如表、行(結構和資料)
u 使用者不可見的系統對象,比如記憶體中的共用資料結構和資料字典行
Oracle如何管理資料並發性和一致性
Oracle在一個多使用者環境中維護資料一致性,是通過使用多版本一致性模型和不同類型的鎖和事務來做到的。這一部分包含下列主題:
u 多版本並發控制
u 語句層級讀一致性
u 事務層級讀一致性
u 真正應用叢集的讀一致性
u Oracle隔離等級
u 提交讀和串列性隔離等級的比較
u 隔離等級的選項
多版本並發控制
Oracle自動為一個查詢提供讀一致性,就是說查詢結果來源於一個單個的時間點(語句層級讀一致性)。Oracle還為事務中所有的查詢提供讀一致性(事務層級讀一致性)。
Oracle使用復原段中維護的資訊來提供這些一致性視圖。復原段包含未提交的事務或最近提交的事務修改的資料的原始值。圖13-1顯示了Oracle如何通過復原段中的資料提供語句層級的讀一致性。
圖13-1 讀一致性和事務
當一個查詢進入執行階段,就確定了當前系統修改號(SCN)。在圖13-1中,系統修改號為10023。在查詢讀取資料區塊時,只有對寫入SCN號可見的塊才會使用。塊中的修改資料(更近的SCN)從復原段中重新構建資料,這些重構資料返回給查詢。因而,每個查詢返回查詢開始的時間的SCN涉及的所有提交資料。在查詢執行時其他事務造成的修改不被採用,確保每個查詢返回的都是一致性資料。
語句層級讀一致性
Oracle總是執行語句層級讀一致性。這可以確保單個查詢返回的所有資料來源於單個時間點(查詢開始的時間點)。因而,一個查詢看不到髒資料或者查詢執行期間其他事務提交的任何改變。查詢執行開始後,只有查詢開始之前提交的資料可以被查詢到。查詢不能看到語句開始執行之後提交的任何資料。
Oracle自動為每個查詢提供一致性結果,確保資料一致性,而不需要使用者參與。包含子查詢的SELECT、INSERT子句,UPDATE和DELETE所有查詢資料,不管是顯式的還是隱式的SQL語句都返回一致性資料。這些語句使用一個查詢來確定要影響哪些資料(SELECT、INSERT、UPDATE或者DELETE)。
一個SELECT語句是一個顯式的查詢,可以包含巢狀查詢或者關聯操作符。一個INSERT語句可以使用巢狀查詢。UPDATE和DELETE語句可以使用WHERE子句或者子查詢來隻影響表中的一些行。
使用INSERT、UPDATE或者DELETE語句確保一系列一致性的結果。但是,他們並不能看到本身DML語句所做的改變。換句話說,這些操作的查詢只能看到這些操作發生改變之前的資料。
注意:如果一個SELECT列表包含一個函數,那麼資料庫在運行PL/SQL函數代碼中SQL的語句層級提供語句層級讀一致性,而不是父層級。例如,一個函數可以訪問另一個使用者已經修改和提交的表資料。對於函數中的每個SELECT執行,都會建立一個新的讀一致性快照。
事務層級讀一致性
Oracle還提供事務層級讀一致性選項。當一個事務運行在串列性(serializable)摸式下,所有的資料訪問反映的資料庫狀態是事務開始的時間。這意味著同一個事務中所有查詢看到的資料都和一個時間點保持一致,當然這個事務本身所做的改變自己可以看到。事務層級的讀一致性會產生重複讀,但不會產生幻影讀。
真正應用叢集的讀一致性
真正應用叢集(RAC)使用cache到cache的塊傳輸機制(cache融合)來從一個執行個體到另一個執行個體傳輸塊的讀一致映像。RAC使用高速度、低等待時間的互聯方式完成傳輸,滿足遠程對資料區塊的請求。
Oracle隔離等級
Oracle提供了3種隔離等級:
隔離等級 |
描述 |
提交讀(read commited) |
這是預設的交易隔離等級。事務中每個執行的查詢只能看到查詢(不是事務)開始之前提交的資料。Oracle查詢不會讀取髒(沒有提交的)資料。 因為Oracle不阻止其他事務通過查詢修改本事務讀取的資料,這個資料可以在本事務的兩個查詢之間由其他事務修改。因而,一個事務中運行給定的查詢兩次會出現幻影讀和不可重複讀取現象。 |
串列性(Serializable) |
串列性事務只能看到事務開始時提交的修改,和本事務通過INSERT、UPDATE和DELETE語句修改的資料。串列性事務不會出現不可重複讀取或幻影讀。 |
唯讀(read-only) |
唯讀事務只能看到事務開始時提交的修改,不允許執行INSERT、UPDATE、DELETE語句。 |
設定隔離等級
應用程式設計人員、應用程式開發人員和資料庫管理員可以根據應用程式和負載情況來為不同的事務選擇合適的隔離等級。你可以在事務開始時通過使用下列語句來設定交易隔離等級。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION READ ONLY;
在每個事務開始用SET TRANSACTION語句設定隔離等級,會增加網路和處理負擔,也可以使用ALTER SESSION語句來為所有以後的事務設定隔離等級:
ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
提交讀隔離等級
Oracle預設隔離等級是提交讀。這個隔離等級對於事務很少衝突的環境是合適的。Oracle讓每個查詢根據它自己的實體化視圖時間運行,因而允許不可重複讀取和多次執行一個查詢導致的幻影讀,但會提供很高的效能。提交讀隔離等級是事務很少衝突的環境的合適的隔離等級。
串列性隔離等級
串列性隔離等級適合如下環境:
u 大資料庫中存在影響少量行的小事務的情況下
u 兩個並行事務很少修改同一行的情況下
u 相對較長時間啟動並執行事務主要是唯讀
串列性隔離等級允許並行事務只能修改那些他們可以修改的部分,就如同事務被調度依次運行一樣。明確來說,Oracle只有確定串列性事務開始時,其他事務修改一個行的修改已經提交,才會允許在這個資料行上使用串列性事務。
為加快這個規則的效率,Oracle在資料區塊上保留控制資訊,顯示了塊中哪些行包含提交的和未提交的資料。某種程度上來說,塊包含最近影響塊上每一行的事務的曆史。可以保留的曆史由CREATE TABLE和ALTER TABLE語句的INITRANS參數來控制。
在某些情況下,Oracle沒有足夠的曆史資訊來確定是否一行被最近的事務修改過。當很多事務並發的修改同一個資料區塊或者在很短的時間發生會出現這種情況(沒有足夠的空間記錄曆史)。如果一個表經常被很多事務修改同一個塊,你可以通過對錶的INITRANS設定很高的值來避免這種情況(沒有足夠的空間記錄曆史)。這使得Oracle在每個塊中分配足夠的空間來記錄最近訪問塊的事務的曆史。
如果串列性事務試圖修改和刪除其他在本事務開始之後的其他事務提交的資料,會產生一個錯誤:
ORA-08177: Cannot serialize access for this transaction
當串列性事務因為Cannot serialize access錯誤而失敗時,應用程式可以採取下列措施:
u 提交這個時間點執行的工作
u 執行另外(但是不同)的語句(可能復原到事務早期構建的儲存點)
u 撤銷整個事務
圖13-2 顯示了Cannot serialize acess錯誤導致的失敗時,一個應用程式復原和重試事務的例子:
圖13-2 串列性事務失敗
提交讀和串列性隔離等級的比較
Oracle為應用開發人員提供了兩種不同規格的隔離等級的選項。提交讀和串列性隔離等級都提供很進階別的一致性和並發性。兩個層級都為降低競爭而提供了讀一致性多版本並發性控制模型和行級互斥鎖的實現,並且都是為真實世界的應用部署設計的。
事務系列一致性
在Oracle中查看提交讀和串列性隔離等級的一個很有用的辦法是考慮下列情境:假定你有一系列資料庫表(或者任何系列資料),這些表的一個特定順序的行讀,在任何特定時間提交的一系列事務。一個操作(查詢或者事務)如果它的所有資料讀是同一系列的提交事務寫入的,那麼這個操作是事務系列一致性的。如果它的資料讀一部分由一系列事務影響,一部分由另一系列事務影響,那麼它就不是事務系列一致性的。操作是否事務系列一致性實際上看是資料庫所處狀態是否反映了單個系列的提交事務。
Oracle為提交讀模式的事務執行的每個語句提供事務系列一致性。串列性模式歲每個事務提供事務系列一致性。
圖13-2匯總了Oracle中提交讀和串列性事務的主要不同。
圖 13-2 提交讀和串列性事務
|
提交讀 |
串列性 |
髒寫(dirty write) |
不允許 |
不允許 |
髒讀(dirty read) |
不允許 |
不允許 |
不可重複讀取(Nonrepeatable read) |
允許 |
不允許 |
幻影讀(Phantoms) |
允許 |
不允許 |
遵從ANSI/ISO SQL 92 |
是 |
是 |
讀取實體化視圖時間 |
語句 |
事務 |
事務系列一致性 |
語句層級 |
事務層級 |
行層級鎖 |
是 |
是 |
讀阻塞寫 |
否 |
否 |
寫阻塞讀 |
否 |
否 |
不同行寫入阻塞寫入 |
否 |
否 |
同一行寫入阻塞寫入 |
|