事務(數據庫引擎)
事務是作為單個邏輯工作單元執行的一系列操作。一個邏輯工作單元必須有四個屬性,稱為原子性、一致性、隔離性和持久性 (ACID) 屬性,只有這樣才能成為一個事務。原子性事務必須是原子工作單元;對於其數據修改,要么全都執行,要么全都不執行。
一致性
事務在完成時,必須使所有的數據都保持一致狀態。在相關數據庫中,所有規則都必須應用於事務的修改,以保持所有數據的完整性。事務結束時,所有的內部數據結構(如 B 樹索引或雙向鏈表)都必須是正確的。
隔離
由並發事務所作的修改必須與任何其他並發事務所作的修改隔離。事務識別數據時數據所處的狀態,要么是另一並發事務修改它之前的狀態,要么是第二個事務修改它之后的狀態,事務不會識別中間狀態的數據。這稱為可串行性,因為它能夠重新裝載起始數據,並且重播一系列事務,以使數據結束時的狀態與原始事務執行的狀態相同。
持久性
事務完成之后,它對於系統的影響是永久性的。該修改即使出現系統故障也將一直保持。
企業數據庫系統(如數據庫引擎 實例)有責任提供一種機制,保證每個事務的物理完整性。數據庫引擎提供:
鎖定設備,使事務保持隔離。
記錄設備,保證事務的持久性。即使服務器硬件、操作系統或數據庫引擎 實例自身出現故障,該實例也可以在重新啟動時使用事務日志,將所有未完成的事務自動地回滾到系統出現故障的點。事務管理特性,強制保持事務的原子性和一致性。事務啟動之后,就必須成功完成,否則數據庫引擎 實例將撤消該事務啟動之后對數據所做的所有修改事務是單個的工作單元。如果某一事務成功,則在該事務中進行的所有數據修改均會提交,成為數據庫中的永久組成部分。如果事務遇到錯誤且必須取消或回滾,則所有數據修改均被清除。
SQL Server 以下列事務模式運行。
自動提交事務
每條單獨的語句都是一個事務。
顯式事務
每個事務均以 BEGIN TRANSACTION 語句顯式開始,以 COMMIT 或 ROLLBACK 語句顯式結束。
隱式事務
在前一個事務完成時新事務隱式啟動,但每個事務仍以 COMMIT 或 ROLLBACK 語句顯式完成。
批處理級事務只能應用於多個活動結果集 (MARS),在 MARS 會話中啟動的 Transact-SQL 顯式或隱式事務變為批處理級事務。當批處理完成時沒有提交或回滾的批處理級事務自動由 SQL Server 進行回滾。
事務並發處理會產生的問題
丟失更新
當兩個或多個事務選擇同一行,然后基於最初選定的值更新該行時,會發生丟失更新問題、 每個事務都不知道其它事務的存在。最后的更新將重寫由其它事務所做的更新,這將導致數據丟失。
臟讀
當第二個事務選擇其它事務正在更新的行時,會發生未確認的相關性問題。第二個事務正在讀取的數據還沒有確認並且可能由更新此行的事務所更改。
不可重復讀
當第二個事務多次訪問同一行而且
每次讀取不同的數據時,會發生不一致的分析問題。不一致的分析與未確認的相關性類似,因為其它事
務也是正在更改第二個事務正在讀取的數據。然而,在不一致的分析中,第二個事務讀取的數據是由已進行了更改的事務提交的。而且,不一致的分析涉及多次(兩次或更多)讀取同一行,而且
每次信息都由其它事務更改;因而該行被非重復讀取。
幻像讀
當對某行執行插入或刪除操作,而該行屬於某個事務正在讀取的行的范圍時,會發生幻像讀問題。事務第一次讀的行范圍顯示出其中一行已不復存在於第二次讀或后續讀中,因為該行已被其它事務刪除。同樣,由於其它事務的插入操作,事務的第二次或后續讀顯示有一行已不存在於原始讀中。
事物的一個典型例子
銀行業務。事務處理應當包括從一個帳戶到另一帳戶的轉帳過程。這一過程屬於事務處理,原因是從某帳戶中支出和在另一帳戶存入兩個動作,必須被作為一個整體來執行——任何一方都不允許失敗。在深入研究ADO.NET編程之前,讓我們先來看看在SQL中是如何進行事務處理的。
SQL事務處理
SQL允許開發人員使用兩個簡單的聲明來使用事務處理
Begin Transaction (啟動事務處理)
Commit Transaction (提交事務處理)
在兩條聲明中的所有語句都成為事務處理的一部分。命令Begin Transaction位於整個事務處理的起始位置,因此其后的所有命令只有在執行到
命令Commit Transaction時才會被一並執行。ADO.NET方法就這么簡單。
ADO.NET事務處理
事務處理需要一個數據庫連接以及一個事務處理對象。在SQL Server和ADO.NET中使用事務處理的難點在於SqlTransaction類。此類名稱隨所使
用的數據庫平台的不同而會有一些變化。例如,對於OLEDB數據庫來說,事務處理類名為OleDbTransaction。
System.Data.SqlClient namespace包括了SqlTransaction類。此類包括了兩個屬性:
Connection:指示同事務處理相關聯的SqlConnection對象;
IsolationLevel:定義事務處理的IsolationLevel。
屬性IsolationLevel是包括如下成員的枚舉對象:
Chaos:從高度獨立的事務處理中出現的pending changes不能被覆蓋;
ReadCommitted:當數據需要被非惡意讀取時,采用共享鎖定(shared locks),但數據仍然可以在事務處理結束時被更新,這造成了非重復性
的數據讀取(nonrepeatable reads)或phantom data的產生;
ReadUncommitted:惡意讀取數據是可能發生的,這表示沒有使用共享鎖定(shared locks),並且沒有實現獨占鎖定(exclusive locks);
RepeatableRead:鎖定查詢中所用到的所有數據,由此避免其他用戶對數據進行更新。在phantom rows仍然可用的狀態下,這可以避免非重復
性的數據讀取(nonrepeatable reads);
Serialisable:在DataSet中進行范圍鎖定,由此防止其他用戶在事務處理結束之前更新數據或在數據庫中插入行;
IsolationLevel定義鎖定記錄的級別,但這一概念不在本文論述范圍之內。對象SqlTransaction也提供了類似的方法。你可以使用以下方法來
進行事務處理:
Commit:提交數據庫事務處理;
Rollback:從未決狀態(pending state)反轉(roll back)事務處理。事務處理一旦被提交后即不能執行此操作;
Save:在事務處理中創建savepoint可以對事務處理的一部分進行反轉,並且指定savepoint名稱。