用Microsoft.net實現資料庫事務(四)

來源:互聯網
上載者:User
資料|資料庫 附A:事務簡介
一個事務是一系列動作作為單個邏輯單位來執行,這意味著這些動作要麼全部成功,要麼全部失敗。如果最後一個動作失敗了,那麼以前的動作應該依次復原,整個狀態回到原先事務開始的狀態。例如,有1000美圓從一個銀行帳戶扣除,轉入另外一個帳戶,那麼事務保證兩個事件只能一起成功,只要有一個失敗,那麼實際就不會發生任何動作,兩個帳戶沒有發生任何改變,錢沒有被存入和扣除。



ACID屬性

有四個屬性經常被用來描述事務:原子性(atomicity), 一致性(consistency), 隔離性(isolation), 持久性(durability)。在一個理想的環境裡,事務符合這四個標準,但是一個事務的隔離等級是可以設定的,原因是設定一個事物的隔離等級為最佳的“可序列化”會增加一種被稱為“死結“情況發生的機率。死結是兩個事務試圖去鎖住已經被對方鎖住的資源,最後一個事務需要復原,這樣另外一個才得以繼續。為了避免這樣的情況發生,你要求降低一個事務的隔離等級來減低它的爭奪力。

l 原子性:事務要作為一個原子單位工作,要不全部執行成功,要麼全部失敗

l 一致性:事務結束後需要保持所有資料的一致性,在一個關聯式資料庫裡,所有的規則要發生在事務引起的變動上,來保持資料的一致性,所有的內部資料結構,如B-tree索引、雙向連接必須在事務結束後保持正確。

l 隔離性:並發事務所作出的變動必須和其他任何並發事務做的變更相隔離。一個事務要麼看到其他事務更改它之前的資料,要麼看到其他事務更改之後的資料,它不能看到臨時的資料,。。。。。。

l 持久性:一個事務結束後,它的結果會持久地存在與系統中,它的變動甚至在系統癱瘓時候也會存在。



事務支援層級



支援層級
描述

隔絕
忽略事務環境

不支援
對象或者頁面不運行在事物環境中. 請求來到時候,不管是否有啟用的事務存在,對象的上下文被建立為非事務類型。

支援
對象或者頁面運行在已有的事務環境中,如果環境沒有事務,則不以事務形式運行。

需要
對象或者頁面運行在已有的事務環境中,如果環境沒有事務,則會建立一個新的。

需要新的
對象或者頁面需要一個事務,每次請求都將建立一個新的事務。


表2:事務支援層級



對於Asp.net,頁面的預設事務層級是“隔絕”,在企業級服務裡面預設層級是“需要”,一般地,我們會在需要事務的第一層對象上順位為“需要”,被調用的對象設定為“支援”。這意味著頂層的對象會建立一個事務,每個被調用的對象被啟用時,將進入這個事務的上下文中。



交易隔離等級



在一個程式中,依據事務的隔離等級將會有三種情況發生。

l 髒讀:一個事務會讀進還沒有被另一個事務提交的資料,所以你會看到一些最後被另一個交易回復掉的資料。

l 讀值不可複現:一個事務讀進一條記錄,另一個事務更改了這條記錄並提交完畢,這時候第一個事務再次讀這條記錄時,它已經改變了。

l 幻影讀:一個事務用Where子句來檢索一個表的資料,另一個事務插入一條新的記錄,並且符合Where條件,這樣,第一個事務用同一個where條件來檢索資料後,就會多出一條記錄。

支援層級
描述

讀入未提交的
最低的隔離等級,這個層級的事務存在髒讀、讀值不複現和幻影讀情況。

讀入提交的
許多資料庫的預設層級,這個層級上你可能遇到讀值不可複現和幻影讀的情況。

可重複讀的
這個層級會遇到幻影讀。

可序列化的
事務之間完全隔離,在COM+ 1.0中,這是唯一選項,但在 COM+ 1.5中,是只是選項之一.


表3:交易隔離等級



一個事務所選擇的隔離等級影響著資料庫怎樣對待其他事務擁有的鎖,你所選擇的隔離等級依賴於你的系統和商務邏輯。例如,一個銀行在客戶取錢之前會檢查它的帳戶餘額,這種情況下,就需要一個隔離等級為可序列化的事務,這樣另外一個取錢動作在這次完成之前將不能執行。如果它們僅需要提供一個帳戶餘額,“讀提交的“將是合適的層級,因為他們僅需要查詢餘額的值,層級的降低會使事務運行更快。



附B 事務開發的建議
l 在一定負荷下面測試事務控制器來保證負荷下死結不會發生

l 儘可能使用預存程序,它們在各種情況仍擁有最好的效能

l 企業級服務為事務的控制提供了一個進階的方式,但使用要謹慎,因為它使效能降低

l 分析你的系統,來決定使用哪一種隔離等級的事務。銀行系統應該使用可序列化的隔離等級



附C 監控事務
沒有一種特別的機制來追蹤資料庫事務和ADO.NET事務。

ASP.NET和企業級服務的事務可以被控制台的元件服務程式來監控,元件服務在開始菜單的管理工具中可以找到。從這個工具中,你可以監控所有通過MS DTC來啟動並執行事務,也就是ASP.NET和企業級服務的事務。你也可以監視事務的執行時間,甚至事務提交、復原、取消的整個過程。



附D 死結


當兩個或兩個以上進程(或線程)互相擁有對方需要的鎖,就會發生死結,一般是在資料庫系統中,但也可能發生在任何的多線程程式中,比如:

事務1
事務 2

鎖定表A
鎖定表B

更新表 A
更新表 B

試圖鎖定表 B
試圖鎖定表 A




在這個時刻,兩個事務都不能繼續進行,因為它們都試圖鎖定對方已經鎖定資源,並且根據事務的規則,兩個事務都不能得知對方的狀態。Sql server會檢測到這種情況的發生,會選擇其中的一個復原,這樣起碼有一個事務可以正常完成了。在這個時刻,控制哪個事務被犧牲的程式不得不決定是重啟這個事務還是拋出錯誤給使用者。一般地,Sql Server會犧牲那個後開始的事務,或者是可以解開最多死結的那個事務。

死結中的一個問題是資料庫會自動做一個復原,這樣會引起中介層的復原代碼裡的一個問題,如果你遇到一個死結,並且在中介層可以截獲異常,當中介層進行復原的時候會得到另外一個異常,這樣你就產生了第二個異常,這是因為Sql Server已經為你做了一次復原,所以你實際上是進行了第二次復原,這時Sql Server卻找不到可以復原的事務。所以一個良好的習慣是把復原的代碼放到一個Try Catch裡面,或者把這個異常匹配到SqlException,並且檢測SqlException異常的代碼,如果是1205,那麼就是死結的情況發生了。

例如:

try

{

// Run SQL Commands in ADO.NET transaction



catch (SqlException sqlex)

{

// Specific catch for deadlock

if (sqlex.Number != 1205)

{

tx.Rollback();

}

orderId = 0;

throw(sqlex);

}



避免死結的方法



有幾個方法可以降低事務發生死結的幾率

l 試圖在事務中用同樣的順序去訪問表,在前面的例子中,如果兩個事務都先訪問表A後訪問表B,那麼就可以避免死結,兩個事務都能成功。

l 避免在事務中有使用者參與/盡量是事務短小,已耗用時間長的事務會增加和其他事務發生死結的機會,在預存程序中運行事務可能會用最短的時間。

l 用一個低的隔離等級,把你的事務的隔離等級設定為最低會使你的業務降低發生死結的風險,預設的,Sql Server把隔離等級設定為“讀取提交的”,這意味著如果一個事務為了讀而鎖定一些資料,另外一個事務允許鎖定它去讀、寫、刪除和更改,這樣會產生“幻影讀“的情況,但在一般的業務中是可以接受的。

l 使用bound connections,在這種條件下,兩個串連共用一個事務/鎖空間,從而避免鎖的衝突。


相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。