網站首頁 編程語言 正文
一、概述
1、事務ACID特性
事務將一系列的工作視為一個工作單元,它具有 ACID 特性:
-
A:Atomicity 不可分性?
也就是說事務中有多項工作,如果有一項工作失敗了,整個事務就算失敗了。 -
C:Consistency 一致性?
事務完成時,全部數據必須維持一致性的狀態。對于關系數據庫,簡單地來說就是沒有破壞數據完整性。 -
I:Isolation 隔離性?
事務與其他事務是隔離的,也就是說一個事務的一項工作對數據進行修改時,如果整個事務還沒有結束,其他事務就無法知道這個數據發生了修改。 -
D:Durability 持久性?
事務完成后,其作用便永遠存在于系統之中。
2、.NET開發者用到的5種事務機制:
- SQL和存儲過程級別的事務。(數據庫事務)
- ADO.NET級別的事務。
- ASP.NET頁面級別的事務。
- 企業級服務COM+事務。
- System.Transactions 事務處理。
這5種事務機制有著各自的優勢和劣勢,分別表現在性能、代碼數量和部署設置等方面。開發人員可以根據項目的實際情況選擇相應的事務機制。
二、數據庫事務
1、不同數據庫的事務規則
數據庫事務是其他事務模型的基礎,當一個事務創建時不同數據庫系統都有自己的規則。
- SQL Server默認在自動提交的模式下工作,每個語句執行完后都會立即提交;
- Oracle則需要你包含一個提交語句。
- 當一個語句通過OLE DB執行時,它執行完后一個提交動作會被附加上去。
例如:SQL Server數據庫T-SQL語句中顯示指定事務
declare @TranName varchar(20);
select @TranName = 'MyTransaction';
begin transaction @TranName;
go
use AdventureWorks;
go
delete from AdventureWorks.HumanResources.JobCandidate where JobCandidateID = 13;
go
commit transaction MyTransaction;
go
或在存儲過程中使用
create procedure Tran1
as
begin tran;
set xact_abort on; --set xact_abort on表示遇到錯誤立即回滾。
insert into P_Category ( CategoryId, Name ) values ( '1', 'test1' );
insert into P_Category ( CategoryId, Name ) values ( '2', 'test2' );
commit tran;
go
2、數據庫事務的優勢和限制
(1)優勢:
- 所有的事務邏輯包含在一個單獨的調用中。
- 擁有運行一個事務的最佳性能。
- 獨立于應用程序。
(2)限制:
- 事務上下文僅存在于數據庫調用中。
- 數據庫代碼與數據庫系統有關。
三、ADO.Net事務
ADO.Net事務為System.Data.Common.DbTransaction類的各種派生類。ADO.Net事務不是分布式事務,不支持跨多個連接,它總是關聯到一個連接上的本地事務上。
ADO.NET 顯式事務占用資源少、速度快,但功能簡單,只能管理單一對象和單一持久資源間的事務。
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString))
{
conn.Open();
using (SqlTransaction tran = conn.BeginTransaction())
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Transaction = tran;
cmd.CommandType = CommandType.Text;
try
{
cmd.CommandText = "insert into TranTable(Priority) values(1)";
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into TranTable(Priority) values(256)";
cmd.ExecuteNonQuery();
tran.Commit();
Response.Write("Ok");
}
catch (SqlException ex)
{
tran.Rollback();
Response.Write("Error:" + ex.Message);
}
}
}
conn.Close();
}
四、System.EnterpriseServices自動事務處理
不需要顯示進行事務處理,運行庫自動創建事務。多個對象能輕松的運行在同一個事務中。但它需要COM+主機模型。
使用此技術的類必須派生自ServicedComponen類。
[Transaction(TransactionOption.Required)]
public class OrderContrl : ServicedComponent
{
[AutoComplete]
public void NewOrder(Order order)
{
using (OrderData data = new OrderData())
{
data.Insert(order);
}
}
}
五、System.Transactions事務
System.Transactions是所有事務處理類的基類。
System.Transactions基礎結構通過支持SQL Server、ADO.NET、MSMQ和Microsoft分布式事務協調器(MSDTC)中啟動的事務,使得整個平臺的事務編程變得簡單和高效。
它既提供了基于Transaction 類的顯式編程模型,也提供了使用TransactionScope類的隱式編程模型,它里面的事務由基礎設施自動管理。強烈建議使用更簡單的隱式開發模型TransactionScope。
1、顯式事務(Explicit Transaction)
提交、回滾事務都由程序員編程來決定的方式,叫“顯式事務(Explicit Transaction)”。Transaction 類及其派生類為顯式事務。
2、Transaction類的派生類
- CommittableTransaction:可提交的事務
- DependentTransaction:依賴事務
- SubordinateTransaction:可以委托的下屬事務
3、Transaction類成員
- Current:獲取或設置環境事務。
- IsolationLevel:獲取事務的隔離級別。
- TransactionInformation:檢索有關某個事務的附加信息。
- DependentClone(DependentCloneOption) :創建事務的依賴復本。
- Rollback() :回滾(中止)事務。
- Dispose():釋放由該對象占用的資源。
- TransactionCompleted:指示事務已完成。
六、可提交的事務:CommitableTransaction(顯式事務)
唯一支持提交的事務類是CommitableTransaction,它直接繼承自Transaction。
CommittableTransaction提供了“Commit”同步方法和“BeginCommit”、“EndCommit”異步方法組合對事務的提交。
創建CommittableTransaction事務并不會自動設置環境事務。
CommittableTransaction事務不能被重用。可以將數據庫連接登記到事務。
注意:只有一個DbConnection時為本地事務;當存在多個DbConnection時才會啟動MSDTC(MSDTC不夠穩定,盡量避免引入分布式服務)
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString))
{
using (CommittableTransaction ct = new CommittableTransaction ())
{
conn.Open();
conn.EnlistTransaction(ct);//將數據庫連接登記到事務
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
try
{
cmd.CommandText = "insert into TranTable(Priority) values(1)";
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into TranTable(Priority) values(256)";
cmd.ExecuteNonQuery();
ct.Commit(); //提交事務
Response.Write("Ok");
}
catch (SqlException ex)
{
ct.Rollback();//回滾事務
Response.Write("Error:" + ex.Message);
}
}
conn.Close();
}
}
七、環境事務:TrasactionScope(隱式事務,推薦)
TransactionScope為隱式事務。它為一組事務型操作創建一個執行范圍,而這個范圍始于TransactionScope創建之時,結束于TransactionScope被回收(調用Dispose方法)。
TransactionScope實現了IDisposable接口,除了Dispose方法之外,僅僅具有一個唯一的方法:Complete()。
目前 TransactionScope 只能處理數據庫的事務,對于其他事務,如 I/O,目前的 .NET 版本無法處理。
using (SqlConnection conn = new SqlConnection("Data Source=.; Initial Catalog=TestDb; Integrated Security=SSPI;"))
{
using (TransactionScope ts = new TransactionScope())
{
conn.Open();
try
{
SqlCommand cmd = new SqlCommand(conn);
cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('測試1','1')";
cmd.ExecuteNonQuery();
cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('測試2','2')";
cmd.ExecuteNonQuery();
ts.Complete();
}
catch (SqlException)
{
}
conn.Close();
}
}
TransactionScope卻有一組豐富的構造函數。我們先來看看這些構造函數相應的參數如何影響TransactionScope對事務控制的行為。
void Main()
{
TransactionOptions transactionOptions = new TransactionOptions()
{
IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
Timeout = new TimeSpan(0, 2, 0)//超時間隔兩分鐘
};
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
Transaction.Current.TransactionCompleted += (sender, args) =>
{
Console.Write(args.Transaction.TransactionInformation.LocalIdentifier);
}
AddStudent(new Student { });
scope.Complete();//提交事務
}
}
public void AddStudent(Student s)
{
SqlConnection conn = new SqlConnection();//環境事務內新建的連接自動附加到事務
//如果連接在TransactionScope建立之前已存在,需要手工用conn.EnlistTrasaction(Transaction.Current)登記事務
conn.Open();
try
{
SqlCommand command = new SqlCommand();
}
catch (Exception ex)
{
throw;
}
}
1、隔離級別IsolationLevel
7個隔離級別之中,Serializable具有最高隔離級別,代表的是一種完全基于序列化(同步)的數據存取方式。按照隔離級別至高向低,7個不同的隔離級別代表的含義如下:
- Serializable:可序列化。(默認,最高級別)可以在事務期間讀取可變數據,但是不可以修改,也不可以添加任何新數據;
- RepeatableRead:可重復讀。可以在事務期間讀取可變數據,但是不可以修改。可以在事務期間添加新數據;
- ReadCommitted:可讀已提交的數據。不可以在事務期間讀取可變數據,但是可以修改它;
- ReadUncommitted:讀未提交的數據。可以在事務期間讀取和修改可變數據;
- Snapshot:快照。可以讀取可變數據。在事務修改數據之前,它驗證在它最初讀取數據之后另一個事務是否更改過這些數據。如果數據已被更新,則會引發錯誤。這樣使事務可獲取先前提交的數據值;
- Chaos:混亂。無法覆蓋隔離級別更高的事務中的掛起的更改;
- Unspecified:未指定。正在使用與指定隔離級別不同的隔離級別,但是無法確定該級別。如果設置了此值,則會引發異常。
2、嵌套環境事務
using (TransactionScope outerScope = new TransactionScope())
{
using (TransactionScope innerScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
//事務型操作
innerScope.Complete();
}
//事務型操作
outerScope.Complete();
}
3、TransactionScopeOption
使用TransactionScopeOptions可以改變TransactionScope的默認事務類型。
- Required:(默認)如果已經存在一個事務,那么這個事務范圍將加入已有的事務。否則,它將創建自己的事務。
- RequiresNew:這個事務范圍將創建自己的事務。
- Suppress:抑制。 將事務范圍內的環境事務設為空,意味著事務范圍內的操作并不受事務的控制。當部分代碼需要留在事務外部時,可以使用該選項。
4、MSDTC組件設置:
一般情況下只要你使用"TransactionScope",都要配置MSDTC,要配防火墻,要開139端口,這個端口不可以更改。
- 如果WEB服務器和數據庫是在同一臺服務器上,TransactionScope使用的是本地事務,這時不需要配置MSDTC。
- 如果WEB服務器和數據庫不在同一臺服務器上,TransactionScope會自動提升事務級別為分布式事務,這時就需要配置MSDTC。
對MSDTC組件設置:控制面板--->管理工具--->服務 中,開啟Distributed Transaction Coordinator 服務。
- 控制面板->管理工具->組件服務->計算機->我的電腦->右鍵->屬性,選擇MSDTC頁, 確認"使用本地協調器"。
- 點擊下方"安全配置"按鈕
- 勾選: "允許網絡DTC訪問","允許遠程客戶端","允許入站","允許出站","不要求進行身份驗證".
- 對于數據庫服務器端, 可選擇"要求對呼叫方驗證"
- 勾選:"啟用事務Internet協議(TIP)事務"。
- 在雙方防火墻中增加MSDTC.exe例外?
可用命令行: netsh firewall set allowedprogram %windir%/system32/msdtc.exe MSDTC enable
八、依賴事務DependentTransaction,跨多個線程調用事務(顯式事務)
一個環境事務綁定到一個線程上,如果新建了一個線程它就不會有第一個線程中的環境事務,兩個線程中的事務完全獨立。
如果多個線程使用同一個環境事務,需要給新線程傳遞一個依賴事務,調用Transaction的DependentClone方法創建依賴事務。
依賴事務通過DependentTransaction類型表示,和CommittableTransaction一樣,DependentTransaction也是Transaction的子類。
DependentTransaction依賴于現有的Transaction對象而存在,相當于被依賴事務的子事務,具有一個唯一的方法成員:Complete。調用這個方法意味著向被依賴事務發送通知,表明所有與依賴事務相關的操作已經完成。
DependentClone方法具有一個DependentCloneOption枚舉類型的參數:
- BlockCommitUntilComplete:表示被依賴事務在提交前會一直等待接收到依賴事務(子事務)的通知(調用Complete或者Rollback方法)或者超過事務設定的超時時限;
- RollbackIfNotComplete:如果被依賴事務在依賴事務(子事務)之前先完成,直接將被依賴的事務回滾,并拋出TransactionAbortedException異常。
下面的代碼示例演示如何創建一個依賴事務來管理兩個并發任務,具體為克隆一個依賴的事務并將其傳遞給輔助線程。
void Main()
{
using (TransactionScope scope = new TransactionScope())
{
DependentTransaction dTx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
Thread thread = new Thread(ThreadMethod);
thread.Start(dTx);
/* Do some transactional work here, then: */
scope.Complete();
}
}
public void ThreadMethod(object transaction)
{
DependentTransaction dTx = transaction as DependentTransaction;
try
{
//將DependentTransaction對象作為TransactionScope的參數,以初始化環境事務
using (TransactionScope ts = new TransactionScope(dTx))
{
/* Perform transactional work here */
ts.Complete();//完成環境事務
}
}
finally
{
dTx.Complete();//完成依賴事務
dTx.Dispose();
}
}
原文鏈接:https://www.cnblogs.com/springsnow/p/9391862.html
相關推薦
- 2022-02-13 淺析ARMv8匯編指令adrp和adr_匯編語言
- 2023-01-11 Android開發中父組件調用子組件方法demo_Android
- 2022-07-09 代理模式(靜態代理和動態代理)
- 2022-11-19 springboot整合使用云服務器上的Redis方法_Redis
- 2022-12-15 Android入門之Toast的使用教程_Android
- 2022-06-29 徹底掌握C語言strcat函數的用法_C 語言
- 2023-01-17 C#實現帶行數和標尺的RichTextBox_C#教程
- 2022-09-26 Go常用技能日志log包創建使用示例_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支