數據庫事務隔離級ORACLE數據庫事務隔離級別介紹


轉自:

https://www.cnblogs.com/andy6/p/6045679.html

本文系轉載,原文地址:http://singo107.iteye.com/blog/1175084

數據庫事務的隔離級別有4個,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決臟讀、不可重復讀、幻讀這幾類問題。

 

√: 可能出現    ×: 不會出現

  臟讀 不可重復讀 幻讀
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×

 

注意:我們討論隔離級別的場景,主要是在多個事務並發的情況下,因此,接下來的講解都圍繞事務並發。

Read uncommitted 讀未提交

公司發工資了,領導把5000元打到singo的賬號上,但是該事務並未提交,而singo正好去查看賬戶,發現工資已經到賬,是5000元整,非常高興。可是不幸的是,領導發現發給singo的工資金額不對,是2000元,於是迅速回滾了事務,修改金額后,將事務提交,最后singo實際的工資只有2000元,singo空歡喜一場。


 

出現上述情況,即我們所說的臟讀,兩個並發的事務,“事務A:領導給singo發工資”、“事務B:singo查詢工資賬戶”,事務B讀取了事務A尚未提交的數據。

當隔離級別設置為Read uncommitted時,就可能出現臟讀,如何避免臟讀,請看下一個隔離級別。

Read committed 讀提交

singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把singo工資卡的2000元轉到另一賬戶,並在singo之前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,為何......

出現上述情況,即我們所說的不可重復讀,兩個並發的事務,“事務A:singo消費”、“事務B:singo的老婆網上轉賬”,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。

當隔離級別設置為Read committed時,避免了臟讀,但是可能會造成不可重復讀。

大多數數據庫的默認級別就是Read committed,比如Sql Server , Oracle。如何解決不可重復讀這一問題,請看下一個隔離級別。

Repeatable read 重復讀

當隔離級別設置為Repeatable read時,可以避免不可重復讀。當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉賬。

雖然Repeatable read避免了不可重復讀,但還有可能出現幻讀。

singo的老婆工作在銀行部門,她時常通過銀行內部系統查看singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)為80元,而singo此時正好在外面胡吃海塞后在收銀台買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨后singo的老婆將singo當月信用卡消費的明細打印到A4紙上,卻發現消費總額為1080元,singo的老婆很詫異,以為出現了幻覺,幻讀就這樣產生了。

注:MySQL的默認隔離級別就是Repeatable read。

Serializable 序列化

Serializable是最高的事務隔離級別,同時代價也花費最高,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免臟讀、不可重復讀,還避免了幻像讀。

 

本文系轉載,原文地址:http://blog.csdn.NET/w_l_j/article/details/7354530

 

[sql]  view plain copy
 
 
  1. 對於同時運行的多個事務, 當這些事務訪問數據庫中相同的數據時, 如果沒有采取必要的隔離機制, 就會導致各種並發問題:  
  2. •   臟讀: 對於兩個事物 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的字段. 之后, 若 T2 回滾, T1讀取的內容就是臨時且無效的.  
  3. •   不可重復讀: 對於兩個事物 T1, T2, T1 讀取了一個字段, 然后 T2 更新了該字段. 之后, T1再次讀取同一個字段, 值就不同了.  
  4. •   幻讀: 對於兩個事物 T1, T2, T1 從一個表中讀取了一個字段, 然后 T2 在該表中插入了一些新的行. 之后, 如果 T1 再次讀取同一個表, 就會多出幾行.  
  5. 數據庫事務的隔離性: 數據庫系統必須具有隔離並發運行各個事務的能力, 使它們不會相互影響, 避免各種並發問題.   
  6. 一個事務與其他事務隔離的程度稱為隔離級別. 數據庫規定了多種事務隔離級別, 不同隔離級別對應不同的干擾程度, 隔離級別越高, 數據一致性就越好, 但並發性越弱  
  7. 數據庫提供了4中隔離級別:  
  8. 隔離級別    描述  
  9. READ UNCOMMITTED(讀未提交數據)    允許事務讀取未被其他事務提交的變更,臟讀、不可重復讀和幻讀的問題都會出現  
  10. READ COMMITED(讀已提交數據)   只允許事務讀取已經被其他事務提交的變更,可以避免臟讀,但不可重復讀和幻讀問題仍然會出現  
  11. REPEATABLE READ(可重復讀)   確保事務可以多次從一個字段中讀取相同的值,在這個事務持續期間,禁止其他事務對這個字段進行更新,可以避免臟讀和不可重復讀,但幻讀的問題依然存在  
  12.   
  13. SERIALIZABLE(串行化)   確保事務可以從一個表中讀取相同的行,在這個事務持續期間,禁止其他事務對該表執行插入、更新和刪除操作,所有並發問題都可以避免,但性能十分低  
  14. Oracle 支持的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE. Oracle 默認的事務隔離級別為: READ COMMITED   
  15. Mysql 支持 4 中事務隔離級別. Mysql 默認的事務隔離級別為: REPEATABLE READ  

 

本文系轉載,原文地址:http://baike.baidu.com/link?url=ECqk10IwUnE8JxHPn-qyzNsqT1XgkD6P3td71Wj3HUT-lWoJ76uU-9hSKtSuCNwp7w56IbIcQ0J00__Qn0z9ra

 

事務隔離級別編輯

本詞條缺少 概述名片圖,補充相關內容使詞條更完整,還能快速升級,趕緊來 編輯吧!
中文名
事務隔離級別
性    質
隔離級別
屬    性
事務
不可重復讀
Non-repeatable Reads
 

1定義編輯

在數據庫操作中,為了有效保證並發讀取數據的正確性,提出的 事務隔離級別

2問題的提出編輯

數據庫是要被廣大客戶所共享訪問的,那么在數據庫操作過程中很可能出現以下幾種不確定情況。

更新丟失

兩個事務都同時更新一行數據,一個事務對數據的更新把另一個事務對數據的更新覆蓋了。這是因為系統沒有執行任何的鎖操作,因此並發事務並沒有被隔離開來。

臟讀

一個事務讀取到了另一個事務未提交的數據操作結果。這是相當危險的,因為很可能所有的操作都被 回滾

不可重復讀

不可重復讀(Non-repeatable Reads):一個事務對同一行數據重復讀取兩次,但是卻得到了不同的結果。
包括以下情況:
(1) 虛讀:事務T1讀取某一數據后,事務T2對其做了修改,當事務T1再次讀該數據時得到與前一次不同的值。
(2)  幻讀(Phantom Reads):事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的數據或者缺少了第一次查詢中出現的數據(這里並不要求兩次查詢的 SQL語句相同)。這是因為在兩次查詢過程中有另外一個事務插入數據造成的。

3解決方案編輯

為了避免上面出現的幾種情況,在標准 SQL規范中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。

未授權讀取

也稱為讀未提交(Read Uncommitted):允許臟讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。

授權讀取

也稱為讀提交(Read Committed):允許 不可重復讀取,但不允許臟讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

可重復讀取(Repeatable Read)

可重復讀取(Repeatable Read):禁止 不可重復讀取和臟讀取,但是有時可能出現幻影數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

序列化(Serializable)

序列化(Serializable):提供嚴格的事務隔離。它要求事務 序列化執行,事務只能一個接着一個地執行,但不能並發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。
隔離級別越高,越能保證數據的完整性和一致性,但是對並發性能的影響也越大。對於多數應用程序,可以優先考慮把 數據庫系統的隔離級別設為 Read Committed。它能夠避免臟讀取,而且具有較好的並發性能。盡管它會導致 不可重復讀、幻讀和第二類丟失更新這些並發問題,在可能出現這類問題的個別場合,可以由應用程序采用 悲觀鎖樂觀鎖來控制。

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 允許幻想讀,不允許不可重復讀和臟讀。在一個事務中,如果在兩次相同條件的讀取操作之間沒有添加記錄的操作,也沒有其他更新操作導致在這個查詢條件下記錄數增多,則兩次讀取結果相同。換句話說,就是在一個事務中第一次讀取的記錄保證不會在這個事務期間發生改動。SQL Server是通過在整個事務期間給讀取的記錄加鎖實現這種隔離級別的,這樣,在這個事務結束前,其他會話不能修改事務中讀取的記錄,而只能等待事務結束,但是SQL Server不會阻礙其他會話向表中添加記錄,也不阻礙其他會話修改其他記錄。

SERIALIZABLE 幻想讀、不可重復讀和臟讀都不允許。在一個事務中,讀取操作的結果是在這個事務開始之前其他事務就已經提交的記錄,SQL Server通過在整個事務期間給表加鎖實現這種隔離級別。在這種隔離級別下,對這個表的所有DML操作都是不允許的,即要等待事務結束,這樣就保證了在一個事務中的兩次讀取操作的結果肯定是相同的。SQL標准所定義的默認事務隔離級別是SERIALIZABLE。

二、Oracle中的隔離級別及實現機制:

Oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。所以Oracle不支持臟讀,即Oracle中不允許一個會話讀取其他事務未提交的數據修改結果,從而防止了由於事務回滾發生的讀取不正確。

Oracle回滾段,在修改數據記錄時,會把這些記錄被修改之前的結果存入回滾段或撤銷段中。Oracle讀取操作不會阻礙更新操作,更新操作也不會阻礙讀取操作,這樣在Oracle中的各種隔離級別下,讀取操作都不會等待更新事務結束,更新操作也不會因為另一個事務中的讀取操作而發生等待,這也是Oracle事務處理的一個優勢所在。

Oracle缺省的配置是Read Committed隔離級別(也稱為語句級別的隔離),在這種隔離級別下,如果一個事務正在對某個表執行 DML操作,而這時另外一個會話對這個表的記錄執行讀取操作,則Oracle會去讀取回滾段或撤銷段中存放的更新之前的記錄,而不會象SQL Server一樣等待更新事務的結束。

Oracle的Serializable隔離級別(也稱為事務級別的隔離),事務中的讀取操作只能讀取這個事務開始之前已經提交的數據結果。如果在讀取時,其他事務正在對記錄執行修改,則Oracle就會在回滾段或撤銷段中去尋找對應的原來未經修改的記錄(而且是在讀取操作所在的事務開始之前存放於回滾段或撤銷段的記錄),這時讀取操作也不會因為相應記錄被更新而等待。

設置隔離級別使用 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語句

兩個並發事務同時訪問數據庫表相同的行時,可能存在以下三個問題:

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 允許幻想讀,不允許不可重復讀和臟讀。在一個事務中,如果在兩次相同條件的讀取操作之間沒有添加記錄的操作,也沒有其他更新操作導致在這個查詢條件下記錄數增多,則兩次讀取結果相同。換句話說,就是在一個事務中第一次讀取的記錄保證不會在這個事務期間發生改動。SQL Server是通過在整個事務期間給讀取的記錄加鎖實現這種隔離級別的,這樣,在這個事務結束前,其他會話不能修改事務中讀取的記錄,而只能等待事務結束,但是SQL Server不會阻礙其他會話向表中添加記錄,也不阻礙其他會話修改其他記錄。

SERIALIZABLE 幻想讀、不可重復讀和臟讀都不允許。在一個事務中,讀取操作的結果是在這個事務開始之前其他事務就已經提交的記錄,SQL Server通過在整個事務期間給表加鎖實現這種隔離級別。在這種隔離級別下,對這個表的所有DML操作都是不允許的,即要等待事務結束,這樣就保證了在一個事務中的兩次讀取操作的結果肯定是相同的。SQL標准所定義的默認事務隔離級別是SERIALIZABLE。

二、Oracle中的隔離級別及實現機制:

Oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。所以Oracle不支持臟讀,即Oracle中不允許一個會話讀取其他事務未提交的數據修改結果,從而防止了由於事務回滾發生的讀取不正確。

Oracle回滾段,在修改數據記錄時,會把這些記錄被修改之前的結果存入回滾段或撤銷段中。Oracle讀取操作不會阻礙更新操作,更新操作也不會阻礙讀取操作,這樣在Oracle中的各種隔離級別下,讀取操作都不會等待更新事務結束,更新操作也不會因為另一個事務中的讀取操作而發生等待,這也是Oracle事務處理的一個優勢所在。

Oracle缺省的配置是Read Committed隔離級別(也稱為語句級別的隔離),在這種隔離級別下,如果一個事務正在對某個表執行 DML操作,而這時另外一個會話對這個表的記錄執行讀取操作,則Oracle會去讀取回滾段或撤銷段中存放的更新之前的記錄,而不會象SQL Server一樣等待更新事務的結束。

Oracle的Serializable隔離級別(也稱為事務級別的隔離),事務中的讀取操作只能讀取這個事務開始之前已經提交的數據結果。如果在讀取時,其他事務正在對記錄執行修改,則Oracle就會在回滾段或撤銷段中去尋找對應的原來未經修改的記錄(而且是在讀取操作所在的事務開始之前存放於回滾段或撤銷段的記錄),這時讀取操作也不會因為相應記錄被更新而等待。

設置隔離級別使用 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語句

 

數據庫事務與隔離級別

http://blog.csdn.Net/jialinqiang/article/details/8723044

 

1.數據庫事務的概念:

 

•事務是指一組相互依賴的操作行為,如銀行交易、股票交易或網上購物。事務的成功取決於這些相互依賴的操作行為是否都能執行成功,只要有一個操作行為失敗,就意味着整個事務失敗。例如,Tom到銀行辦理轉賬事務,把100元錢轉到Jack的賬號上,這個事務包含以下操作行為:

–(1)從Tom的賬戶上減去100元。

–(2)往Jack的賬戶上增加100元。

•顯然,以上兩個操作必須作為一個不可分割的工作單元。假如僅僅第一步操作執行成功,使得Tom的賬戶上扣除了100元,但是第二步操作執行失敗,Jack的賬戶上沒有增加100元,那么整個事務失敗。

•數據庫事務是對現實生活中事務的模擬,它由一組在業務邏輯上相互依賴的SQL語句組成。

 

2.數據庫事務的生命周期:

 

3.聲明事務的邊界:

 

•事務的開始邊界。

•事務的正常結束邊界(COMMIT):提交事務,永久保存被事務更新后的數據庫狀態。

•事務的異常結束邊界(ROLLBACK):撤銷事務,使數據庫退回到執行事務前的初始狀態。

 

(1).在mysql.exe中聲明事務:

 

•每啟動一個mysql.exe程序,就會得到一個單獨的數據庫連接。每個數據庫連接都有個全局變量@@autocommit,表示當前的事務模式,它有兩個可選值:

–0:表示手工提交模式。

–1:默認值,表示自動提交模式。

•如果要察看當前的事務模式,可使用如下SQL命令:

–mysql> select @@autocommit

•如果要把當前的事務模式改為手工提交模式,可使用如下SQL命令:

–mysql> set autocommit=0;

 

——在自動提交模式下提交事務:

•在自動提交模式下,每個SQL語句都是一個獨立的事務。如果在一個mysql.exe程序中執行SQL語句:

–mysql>insert into ACCOUNTS values(1,'Tom',1000);

•MySQL會自動提交這個事務,這意味着向ACCOUNTS表中新插入的記錄會永久保存在數據庫中。此時在另一個mysql.exe程序中執行SQL語句:

–mysql>select * from ACCOUNTS;

•這條select語句會查詢到ID為1的ACCOUNTS記錄。這表明在第一個mysql.exe程序中插入的ACCOUNTS記錄被永久保存,這體現了事務的ACID特性中的持久性。

 

——在手工模式下提交事務:

•在手工提交模式下,必須顯式指定事務開始邊界和結束邊界:

–事務的開始邊界:begin

–提交事務:commit

–撤銷事務:rollback

例:

–mysql>begin;
–mysql>select * from ACCOUNTS;
–mysql>commit;

 

(2).通過JDBC API聲明事務邊界:

 

• Connection提供了以下用於控制事務的方法:

–setAutoCommit(boolean autoCommit):設置是否自動提交事務

–commit():提交事務

–rollback():撤銷事務

例:

try {

con = Java.sql.DriverManager.getConnection(dbUrl,dbUser,dbPwd);

//設置手工提交事務模式

con.setAutoCommit(false);

stmt = con.createStatement();

//數據庫更新操作1

stmt.executeUpdate("update ACCOUNTS set BALANCE=900 where ID=1 ");

//數據庫更新操作2

stmt.executeUpdate("update ACCOUNTS set BALANCE=1000 where ID=2 ");

con.commit(); //提交事務

}catch(Exception e) {

try{

con.rollback(); //操作不成功則撤銷事務

}catch(Exception ex){

//處理異常

……

}

//處理異常

……

}finally{…}

 

(3).通過hibernate API聲明事務邊界:

 

•聲明事務的開始邊界:Transaction tx=session.beginTransaction();

•提交事務: tx.commit();

•撤銷事務: tx.rollback();

 

4.多個事務並發時的並發問題:

 

•第一類丟失更新:撤銷一個事務時,把其他事務已提交的更新數據覆蓋。

•臟讀:一個事務讀到另一事務未提交的更新數據。

•虛讀:一個事務讀到另一事務已提交的新插入的數據。

•不可重復讀:一個事務讀到另一事務已提交的更新數據。

•第二類丟失更新:這是不可重復讀中的特例,一個事務覆蓋另一事務已提交的更新數據。

 

以取款事務和支票轉賬事務例:

•取款事務包含以下步驟:

–(1)某銀行客戶在銀行前台請求取款100元,出納員先查詢賬戶信息,得知存款余額為1000元。

–(2)出納員判斷出存款額超過了取款額,就支付給客戶100元,並將賬戶上的存款余額改為900元。

•支票轉賬事務包含以下步驟:

–(1)某出納員處理一轉帳支票,該支票向一帳戶匯入100元。出納員先查詢賬戶信息,得知存款余額為900元。

–(2)出納員將存款余額改為1000元。

 

並發運行的兩個事務導致臟讀:

取款事務在T5時刻把存款余額改為900元,支票轉賬事務在T6時刻查詢賬戶的存款余額為900元,取款事務在T7時刻被撤銷,支票轉賬事務在T8時刻把存款余額改為1000元。

由於支票轉賬事務查詢到了取款事務未提交的更新數據,並且在這個查詢結果的基礎上進行更新操作,如果取款事務最后被撤銷,會導致銀行客戶損失100元。

 

並發運行的兩個事務導致第二類更新丟失:

取款事務在T5時刻根據在T3時刻的查詢結果,把存款余額改為1000-100元,在T6時刻提交事務。支票轉賬事務在T7時刻根據在T4時刻的查詢結果,把存款余額改為1000+100

元。由於支票轉賬事務覆蓋了取款事務對存款余額所做的更新,導致銀行最后損失100元。

 

5.數據庫的隔離級別:

 

 

(1).隔離級別與並發性能的關系:

(2).設置隔離級別的原則:

 

•隔離級別越高,越能保證數據的完整性和一致性,但是對並發性能的影響也越大。

•對於多數應用程序,可以優先考慮把數據庫系統的隔離級別設為Read Committed,它能夠避免臟讀,而且具有較好的並發性能。盡管它會導致不可重復讀、虛讀

和第二類丟失更新這些並發問題,在可能出現這類問題的個別場合,可以由應用程序采用悲觀鎖樂觀鎖來控制。

 

(3)在mysql.exe程序中中設置隔離級別:

 

•每啟動一個mysql.exe程序,就會獲得一個單獨的數據庫連接。每個數據庫連接都有個全局變量@@tx_isolation,表示當前的事務隔離級別。MySQL默認的隔離

級別為Repeatable Read。如果要察看當前的隔離級別,可使用如下SQL命令:

–mysql> select @@tx_isolation;

•如果要把當前mysql.exe程序的隔離級別改為Read Committed,可使用如下SQL命令:

–mysql> set transaction isolation level read committed;

 

(4)在Hibernate中設置隔離級別:

 

 

•在Hibernate的配置文件中可以顯式的設置隔離級別。每一種隔離級別都對應一個整數:

–1:Read Uncommitted

–2:Read Committed

–4:Repeatable Read

–8:Serializable

•例如,以下代碼把hibernate.cfg.xml文件中的隔離級別設為Read Committed:

hibernate.connection.isolation=2

對於從數據庫連接池中獲得的每個連接,Hibernate都會把它改為使用Read Committed隔離級別。

 

文章可以轉載,必須以鏈接形式標明出處。

 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM