oracle 事務隔離級別
事務不同引發的狀況:
髒讀(dirty reads)
乙個事務讀取另乙個事務尚未提交的修改時,產生髒讀
很多資料庫允許髒讀以避免排它鎖的競爭。
不可重複讀(nonrepeatable reads)
同一查詢在同一事務中多次進行,由於其他提交事務所做的修改或刪除,每次返回不同的結果集,此時發生非重複讀。
幻讀(phantom reads)
同一查詢在同一事務中多次進行,由於其他提交事務所做的插入操作,每次返回不同的結果集,此時發生幻像讀。
資料庫操作的隔離級別
未提交讀(read uncommitted)
提交讀(read committed)
重複讀(repeatable read)
序列化(serializable)
oracle預設隔離級別read committed (statement level serialization)
每乙個語句,在語句開始時,會獲取乙個此刻的資料快照。
乙個事務有多條語句,如果語句之間存在其它完成的事務,這可能引起不可持續讀和幻讀。
新建乙個測試表books:
name,code,price三個字段
新增兩條測試資料
使用pl/sql和j**a程式模擬併發
不允許髒讀測試:
程式段首先查詢code是qqq的書的**
複製** **如下:
//獲取連線 省略
pstat = conn.preparestatement("select price from books where code='qqq'");
rs = pstat.executequery();
while(rs.next())
close();
輸出結果:price:15.0
然後pl/sql執行更新
複製** **如下:
update books set price=18 where code='qqq';
!pl/sql設定成手動更新,不自動更新
在執行上面j**a查詢**
輸出仍是price:15.0,說明讀不到pl/sql中未提交的執行結果,即不允許髒讀
pl/sql 執行
commit;
在執行j**a查詢:
輸出結果:price:18.0
會有不可重複讀何幻讀的現象發生就不用測試了吧,
這兩種現象都是針對提交後事物的讀引起的,read commited隔離級別是允許對提交後
的事物進行讀的。
隔離級別:重複讀(repeatable read)
這個不允許髒讀,不可重複讀,但是會有幻讀現象。
這個oracle不支援,不好測試。
理解的話就是如果一條查詢語句查詢的內容有其它事物正在更新的時候,這
查詢處於等待狀態,直到先前事物提交更新後,才會執行本條查詢。也就是
查詢的時候也會有鎖,需要等待併發的事物釋放鎖。然後自己獲取到鎖,執行
自己事物。這樣查詢也加鎖,併發性更低
select ... for update 就是這樣可以避免不可重複讀的發生
隔離級別:serializable
這個就更嚴格了,事物執行是乙個乙個的。乙個事務中的語句共享同乙個資料快照(在事務開始時存在的資料)。
是事物級別的,髒讀,不可重複讀,幻讀根本就沒有機會發生。
前面像read committed都是語句級別的,以語句為單元。
比如 read committed乙個事物a有a(select),b(select),c(update)三條語句
當a事物執行a,b的時候,若有b事物執行更新操作,是有可能的
因為a,b是不加鎖的
例子:
複製** **如下:
//獲取連線和關閉連線** 省略
//不自動提交
conn.setautocommit(false);
/**
程式設計客棧* a 查詢
*/
pstat = conn.preparestatement("select price from books where code='qqq'");
rs = pstat.executequery();
while(rs.next())
close();
/**
* 暫停一會,用pl/sql執行b事務
* update books set price=15 where code='qqq';
* commit;
*/
thread.sleep(10000);
/**
* 如果這裡再執行a查詢的話,和第一次查詢結果就不一樣,因為中間有b事務的提交更新
* 修改,這也是不可重複讀
*/
//b 更新
pstat = conn.preparestatement("update books set price=price+10 where code='qqq'");
pstat.executeupdate();
close();
//c 查詢
pstat = conn.preparestatement("select price from books where code='qqq'");
rs = pstat.executequery();
while(rs.next())
close();
//提交事務
conn.commit();
if(conn != null)
上面執行的順序,事務b是在a的執行過程中執行的。
以上通過例項介紹了oracle資料庫隔離級別的相關內容,希望對大家有所幫助。
下面是一些補充:
資料庫中的事務基本作用是將資料庫從一致狀態轉換到另一種一致狀態,那麼事務隔離級別就是定義了乙個事務對於另外乙個事務做出的修改有多「敏感」。也就是不同的隔離級別定義了事務相互影響的程度,下面分別介紹一下幾種不同的隔程式設計客棧離級別。
1. read uncommitted
其實,oracle不支援這種隔離級別。這種隔離級別允許髒讀(也就是可以讀取到使用者未提www.cppcns.com交的資料),支援這種隔離級別的資料庫主要是為了支援非阻塞讀,但是oracle預設支援非阻塞讀,所以oracle裡面不支援這種隔離級別。下面舉乙個例子:
如上圖所示,假設某一家銀行要統計所有賬號總共有多少金額。事務a負責統計,事務a從第一行開始讀取。假設讀取到100行的時候,事務b從賬號123轉了400元到賬戶987(事務b還未提交),支援髒讀的資料庫當事務a讀取到342023行的時候,就會得到500元,從而多加了400元。
2. read committed
這種隔離級別指的是,事務只能讀取已經提交的資料,(但是支援可重複讀與幻想讀)是oracle資料庫預設的隔離模式。其實這種隔離級別在別的資料庫裡面可能還是會「退化」得像髒讀一樣。就看前面那個例子,假設在事務a讀取到342023行前,事務b提前鎖定了這一行,並將金額由100改成了500。那麼事務a讀取到這一行的時候,發現已經被其他事務鎖定了,於是進行等待,直到事務b提交。但是當事務b提交之後,事務a還是讀取到了500這乙個錯誤資訊,這樣就和髒讀一樣的了,而且還讓使用者等待這個錯誤的答案。
3. repeatable read
這種隔離級別不支援髒讀,不支援可重複讀,支援幻想讀。主要是為了得到一致性的答案與防止丟失更新。
a. 得到一致性答案
在oracle裡面這個通過多版本機制得到了實現,但是在其他的資料庫需要通過加鎖機制進行控制,就以上乙個例子為例,怎樣才能統計出正確的總金額呢,事務a在讀取每一行的時候,給每一行加上共享讀鎖,這樣當事務b執行從賬號123轉400元到賬戶987的時候。先是操作第一行將賬戶123的金額由500修改成100,但是第一行已經被事務a鎖定,於是等待,這樣事務a能夠讀取到正確的資料。但是如果事務b執行的操作是從賬戶987轉50元到賬戶123的時候,事務b先操作第342023行,發現沒有被鎖定,於是鎖定將金額由100修改成50,然後操作第一行,發現鎖定了於是等待。而事務a讀取到342023行的時候,發現這一行已經被事務b鎖定於是等待,這樣就陷入了死鎖。
b. 丟失更新
在採用共享讀鎖的資料庫中,這種隔離級別可以防止丟失更新,比如事務1先讀取了第a行然後修改了這一行的c列(其他列也www.cppcns.com修改了只是值還和以前一樣,因為程式設計師都是整行的更新)。這個時候事務2想也想修改a行的時候會被阻塞,防止事務1的更新被覆蓋。
4. seaializable
不允許髒讀,重複讀與幻想讀,最高的隔離級別。這種隔離級別標明事務a在運算元據庫的時候好像就只有事務a在操作,沒有其他事務在運算元據庫一樣。
oracle 中是這樣實現 serializable 事務的:原本通常在語句級得到的讀一致性現在可以擴充套件到事務級。也就是在事務執行的那一刻,將這個事務將要操作的資料拍了一張**。
從上面的例子我們可以看出,其他資料庫採用共享讀鎖來解決統計總金額問題是沒有oracle多版本機制靈活的,其一嚴重影響了程式的併發性,讀阻程式設計客棧塞了寫。其二可能引起死鎖。
本文標題: oracle 資料庫隔離級別學習
本文位址:
ORACLE資料庫事務隔離級別
事務隔離級別 乙個事務對資料庫的修改與並行的另乙個事務的隔離程度。兩個併發事務同時訪問資料庫表相同的行時,可能存在以下三個問題 1 幻想讀 事務t1讀取一條指定where條件的語句,返回結果集。此時事務t2插入一行新記錄,恰好滿足t1的where條件。然後t1使用相同的條件再次查詢,結果集中可以看到...
ORACLE資料庫事務隔離級別
oracle資料庫事務隔離級別 事務隔離級別 乙個事務對資料庫的修改與並行的另乙個事務的隔離程度。兩個併發事務同時訪問資料庫表相同的行時,可能存在以下三個問題 1 幻想讀 事務t1讀取一條指定where條件的語句,返回結果集。此時事務t2插入一行新記錄,恰好滿足t1的where條件。然後t1使用相同...
ORACLE資料庫事務隔離級別
事務隔離級別 乙個事務對資料庫的修改與並行的另乙個事務的隔離程度。兩個併發事務同時訪問資料庫表相同的行時,可能存在以下三個問題 1 幻想讀 事務t1讀取一條指定where條件的語句,返回結果集。此時事務t2插入一行新記錄,恰好滿足t1的where條件。然後t1使用相同的條件再次查詢,結果集中可以看到...