.Net系列 Transaction 事務


Transactions

事務(Transaction),一般是指要做的或所做的事情。在計算機術語中是指訪問並可能更新數據庫中各種數據項的一個程序執行單元(unit)。在計算機術語中,事務通常就是指數據庫事務。

應用場景:

應用程序需要執行多個操作,包括一個或多個數據庫命令
* 其中一個數據庫命令失敗或某些其他操作失敗(例如注冊表更新)
* 多項行動是為了一起工作。應用程序現在處於不一致的狀態。
我們使用 transaction 來解決這個問題,transaction 就是執行所需的一組命令原子操作
➢如果所有命令都成功完成,則 transaction 成功。
➢如果有任何命令失敗,整個 transaction 將 rollback 到 pre-transaction 狀態。
➢造成rollback的故障不一定與數據庫相關。

ACID transaction properties 屬性

All database management systems adhere to a set of properties known as the ACID properties:
並非任意的對數據庫的操作序列都是數據庫事務。數據庫事務擁有以下四個特性,習慣上被稱之為ACID特性

Atomicity: “All or nothing.” No partial success. Either the transaction succeeds in its entirety or it fails.
原子性(Atomicity):事務作為一個整體被執行,包含在其中的對數據庫的操作要么全部被執行,要么都不執行。

Consistency: Integrity constraints are met. Acceptable for inconsistency to occur during the transaction, but must be completely consistent upon completion.
一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是數據庫中的數據應滿足完整性約束。

Isolation: The extent to which other transactions can “see” changes made by other transactions while they are executing.
隔離性(Isolation):多個事務並發執行時,一個事務的執行不應影響其他事務的執行。

Durability: Guarantees permanent survival of data after the commit is complete.
持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中

.NET 頁、XML Web services方法或 .NET Framework 類一旦被標記為參與事務,它們將自動在事務范圍內執行。您可以通過在頁、XML Web services 方法或類中設置一個事務屬性值來控制對象的事務行為。特性值反過來確定實例化對象的事務性行為。因此,根據聲明特性值的不同,對象將自動參與現有事務或正在進行的事務,成為新事務的根或者根本不參與事務。聲明事務屬性的語法在 .NET Framework 類、.NET 頁和 XML Web services 方法中稍有不同。

Isolation Level 事務隔離層級

A property of the TransactionScope object, specifying the degree of transaction isolation.
隔離級別定義了事務與事務之間的隔離程度。
隔離級別與並發性是互為矛盾的:隔離程度越高,數據庫的並發性越差;隔離程度越低,數據庫的並發性越好。

Serializable (highest): read, write, and range locks (if necessary) used until end of the transaction.
序列化:提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接着一個地執行,不能並發執行。僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。

RepeatableRead: Same, except no range locks. Other transactions can delete/update resulting in phantom reads.
可重復讀取:禁止不可重復讀取和臟讀取,但是有時可能出現幻讀數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

Snapshot: Instead of write-locking, “snapshot” of to-be-written data is taken and served to reading transactions.
“snapshot” 取代 write-locking寫鎖定,獲取待寫入數據的 snapshot 並將其送達
reading transactions。這個其實是tradeoff,並沒有復制所有的數據,
搞清楚OS中的 readlock,writelock, rangelock。
讀取數據時,可以保證讀操作讀取的行是事務開始時可用的最后提交版本。這意味着這種隔離級別可以保證讀取的是已經提交過的數據,並且可以實現可重復讀,也能確保不會幻讀。

ReadCommitted: No dirty reads (not-yet-committed data from other transactions not visible), but non-repeatable reads may occur. (Default IL for SQL Server)
授權讀取:在commit之前,不允許dirty read(尚未提交的其他交易數據不可見)。但可能會發生不可重復的讀取,因為反復讀取會有不一樣的結果。 (SQL Server的默認level)允許不可重復讀取,但不允許臟讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

ReadUncommitted (lowest): Dirty reads permitted. One transaction can see another transaction’s changes before the commit.
未授權讀取: 允許臟讀,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。不管事務B何時Commit,事務A中的SELECT語句2都可以讀出數據(有可能是臟數據,因事務B可能會ROLLBACK),且與語句1的數據不同。

 

Isolation Levels Illustrated

這個圖按照時間順序,上至下操作。
1. UnCommitted level時,只要A做出了更改,B就會讀取到這個更改,不存在Commit的考慮。

Committed level時,T1讀取了數據A,T2得到一樣數據A。T1把數據修改為數據B,T2再讀取依然是數據A。commit之后,T2 就會得到數據B。不可重復讀。

RepeatableRead和Serializable level時,區別在於Range Lock。T2 在commit之前,讀取的都是未修改的數據A。

選擇什么level很多程度上取決於我們對數據變化的重視程度。

 

下面是個例子:

 

關於 三種 讀

臟讀 :臟讀就是指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問這個數據,然后使用了這個數據。

不可重復讀 :是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那么,在第一個事務中的兩 次讀數據之間,由於第二個事務的修改,那么第一個事務兩次讀到的的數據可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱為是不 可重復讀。例如,一個編輯人員兩次讀取同一文檔,但在兩次讀取之間,作者重寫了該文檔。當編輯人員第二次讀取文檔時,文檔已更改。原始讀取不可重復。如果 只有在作者全部完成編寫后編輯人員才可以讀取文檔,則可以避免該問題。

幻讀 : 幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,比如這種修改涉及到表中的“全部數據行”。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入“一行新數據”。那么,以后就會發生操作第一個事務的用戶發現表中還存在沒有修改的數據行,就好象發生了幻覺一樣.一般解決幻讀的方法是增加范圍鎖RangeS,鎖定檢索范圍為只讀,這樣就避免了幻讀。

最高隔離級別SERIALIZABLE_READ可以保證不出現幻讀的問題。

 

Transactions in EF

在Entity Framework中使用 transaction 更容易:事務自動發生在同一個事務中上下文。

SaveChanges 就自動有了transaction,是readcommitted level。
* Transactions using this technique are limited to the scope of the context in the using clause
* Transactions spanning multiple contexts require heavier artillery: TransactionScope
- You must add the reference System.Transactions
* Connecting to multiple databases requires enabling MSDTC on the server.

 

在EF版本6中:


SaveChanges之后還要Commit。
Try block之后Catch,任何問題發生都可以rollback。

 

如果我們希望用其他level的isolation,則需要用TransactionScope object:
這里有 TransactionScope constructor。
需要兩個參數,一個是new,一個是transaction option object 設置 isolation level,這里設置成最低的 Uncommitted。

下面的例子並未完成,因為沒有rollback

 

Change tracking

當修改EF對象或從容器中添加/刪除EF對象時…
* Changes are tracked locally by the context
* You can stop change tracking by detaching an entity from the context. (example to follow)

Calling SaveChanges does the following:
* Generates and executes SQL commands 生成並執行SQL命令
* Commits changes to the database in a single transaction 在單個事務中提交對數據庫的更改
* Resets tracking information重置跟蹤信息

改變跟蹤 attaching/detaching 例子


c2 脫離了,改變不再被記錄。Savechanges時,只有c1 會被記載,c2還是會被放在course的container里,在Course里還是可以看見c1和c2,但是數據庫里只有c1。


---------------------

原文:https://blog.csdn.net/CheungKaiwei/article/details/79775156
作者:CheungKaiwei 


免責聲明!

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



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