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

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

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

 

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

  髒讀 不可重複讀 幻讀
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×

 

注意:咱們討論隔離級別的場景,主要是在多個事務併發的狀況下,所以,接下來的講解都圍繞事務併發。數據庫

Read uncommitted 讀未提交

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


 

出現上述狀況,即咱們所說的髒讀,兩個併發的事務,「事務A:領導給singo發工資」、「事務B:singo查詢工資帳戶」,事務B讀取了事務A還沒有提交的數據。併發

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

Read committed 讀提交

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

出現上述狀況,即咱們所說的不可重複讀,兩個併發的事務,「事務A:singo消費」、「事務B:singo的老婆網上轉帳」,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。性能

當隔離級別設置爲Read committed時,避免了髒讀,可是可能會形成不可重複讀。url

大多數數據庫的默認級別就是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數據庫事務隔離級別介紹

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

一、幻想讀:事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,剛好知足T1的where條件。而後T1使用相同的條件再次查詢,結果集中能夠看到T2插入的記錄,這條新紀錄就是幻想。

二、不可重複讀取:事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄,而後T1再次查詢,發現與第一次讀取的記錄不一樣,這稱爲不可重複讀。

三、髒讀:事務T1更新了一行記錄,還未提交所作的修改,這個T2讀取了更新後的數據,而後T1執行回滾操做,取消剛纔的修改,因此T2所讀取的行就無效,也就是髒數據。

1、爲了處理這些問題,SQL標準定義瞭如下幾種事務隔離級別:

READ UNCOMMITTED 幻想讀、不可重複讀和髒讀都容許。一個會話能夠讀取其餘事務未提交的更新結果,若是這個事務最後以回滾結束,這時的讀取結果就多是不正確的,因此多數的數據庫都不會運用這種隔離級別。

READ COMMITTED 容許幻想讀、不可重複讀,不容許髒讀。一個會話只能讀取其餘事務已提交的更新結果,不然,發生等待,可是其餘會話能夠修改這個事務中被讀取的記錄,而沒必要等待事務結束,顯然,在這種隔離級別下,一個事務中的兩個相同的讀取操做,其結果可能不一樣。

REPEATABLE READ 容許幻想讀,不容許不可重複讀和髒讀。在一個事務中,若是在兩次相同條件的讀取操做之間沒有添加記錄的操做,也沒有其餘更新操做致使在這個查詢條件下記錄數增多,則兩次讀取結果相同。換句話說,就是在一個事務中第一次讀取的記錄保證不會在這個事務期間發生改動。SQL Server是經過在整個事務期間給讀取的記錄加鎖實現這種隔離級別的,這樣,在這個事務結束前,其餘會話不能修改事務中讀取的記錄,而只能等待事務結束,可是SQL Server不會阻礙其餘會話向表中添加記錄,也不阻礙其餘會話修改其餘記錄。

SERIALIZABLE 幻想讀、不可重複讀和髒讀都不容許。在一個事務中,讀取操做的結果是在這個事務開始以前其餘事務就已經提交的記錄,SQL Server經過在整個事務期間給表加鎖實現這種隔離級別。在這種隔離級別下,對這個表的全部DML操做都是不容許的,即要等待事務結束,這樣就保證了在一個事務中的兩次讀取操做的結果確定是相同的。SQL標準所定義的默認事務隔離級別是SERIALIZABLE。

2、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新增的記錄了。

當下列事件發生時,事務就開始了:

一、鏈接到數據庫,並執行第一條DML語句 
二、前一個事務結束後,又輸入了另外一條DML語句

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

一、幻想讀:事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,剛好知足T1的where條件。而後T1使用相同的條件再次查詢,結果集中能夠看到T2插入的記錄,這條新紀錄就是幻想。

二、不可重複讀取:事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄,而後T1再次查詢,發現與第一次讀取的記錄不一樣,這稱爲不可重複讀。

三、髒讀:事務T1更新了一行記錄,還未提交所作的修改,這個T2讀取了更新後的數據,而後T1執行回滾操做,取消剛纔的修改,因此T2所讀取的行就無效,也就是髒數據。

1、爲了處理這些問題,SQL標準定義瞭如下幾種事務隔離級別:

READ UNCOMMITTED 幻想讀、不可重複讀和髒讀都容許。一個會話能夠讀取其餘事務未提交的更新結果,若是這個事務最後以回滾結束,這時的讀取結果就多是不正確的,因此多數的數據庫都不會運用這種隔離級別。

READ COMMITTED 容許幻想讀、不可重複讀,不容許髒讀。一個會話只能讀取其餘事務已提交的更新結果,不然,發生等待,可是其餘會話能夠修改這個事務中被讀取的記錄,而沒必要等待事務結束,顯然,在這種隔離級別下,一個事務中的兩個相同的讀取操做,其結果可能不一樣。

REPEATABLE READ 容許幻想讀,不容許不可重複讀和髒讀。在一個事務中,若是在兩次相同條件的讀取操做之間沒有添加記錄的操做,也沒有其餘更新操做致使在這個查詢條件下記錄數增多,則兩次讀取結果相同。換句話說,就是在一個事務中第一次讀取的記錄保證不會在這個事務期間發生改動。SQL Server是經過在整個事務期間給讀取的記錄加鎖實現這種隔離級別的,這樣,在這個事務結束前,其餘會話不能修改事務中讀取的記錄,而只能等待事務結束,可是SQL Server不會阻礙其餘會話向表中添加記錄,也不阻礙其餘會話修改其餘記錄。

SERIALIZABLE 幻想讀、不可重複讀和髒讀都不容許。在一個事務中,讀取操做的結果是在這個事務開始以前其餘事務就已經提交的記錄,SQL Server經過在整個事務期間給表加鎖實現這種隔離級別。在這種隔離級別下,對這個表的全部DML操做都是不容許的,即要等待事務結束,這樣就保證了在一個事務中的兩次讀取操做的結果確定是相同的。SQL標準所定義的默認事務隔離級別是SERIALIZABLE。

2、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新增的記錄了。

當下列事件發生時,事務就開始了:

一、鏈接到數據庫,並執行第一條DML語句 
二、前一個事務結束後,又輸入了另外一條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隔離級別。

相關文章
相關標籤/搜索