背景:
事务是数据库管理系统的一个基本概念,事务具有四个基本特点,即ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),通过事务机制可以保证数据库的一致性和完整性。
不过数据库事务只能在数据库实例的同一个会话级别进行事务控制。而分布式事务可以协调一个数据库实例多个会话之间的操作,甚至是多个数据库实例之间的数据库操作,并保持事务特性。但是原则上我们不推荐使用分布式事务,因为分布式事务对资源消耗较多,执行效率较差。
然而一直以来,我们对分布式事务的代码使用和效果都存在误解:使用了TransactionScope就一定会开启分布式事务吗?
验证:
我们做一个简单的Demo:两个连接字符串完全相同,ADO.NET会复用连接池中的连接,结果会如何?
using (TransactionScope ts = new TransactionScope()) { SqlConnection conn; conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa"); conn.Open(); SqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "select 1 as tkk"; cmd.ExecuteNonQuery(); conn.Close(); conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa"); conn.Open(); cmd = conn.CreateCommand(); cmd.CommandText = "select 2 as tkk"; cmd.ExecuteNonQuery(); conn.Close(); ts.Complete(); } Console.WriteLine("OK"); Console.ReadKey();
奇怪的事情发生了,并没有看到我们的以为的分布式事务!!!
我们更改其中的一个连接字符串,使得ADO.NET认为是两个数据源,这样才会真正意义上开启分布式事务。
using (TransactionScope ts = new TransactionScope()) { SqlConnection conn; conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa"); conn.Open(); SqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "select 1 as tkk"; cmd.ExecuteNonQuery(); conn.Close(); conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa;"); --加了一个分号,不共享连接 conn.Open(); cmd = conn.CreateCommand(); cmd.CommandText = "select 2 as tkk"; cmd.ExecuteNonQuery(); conn.Close(); ts.Complete(); } Console.WriteLine("OK"); Console.ReadKey();
让我们看一下分布式事务是如何协调每个数据库连接,当前的案例我们使用的是同一个数据库,所以虽然建立了两个数据库连接,但最终在数据库层面仍然是同一事务ID。
如果我们打开的是两个不同数据库实例,将会看到什么样的结果呢? try it。。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?