栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

分布式事务如何在线程环境中与同一个数据库建立多个连接?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

分布式事务如何在线程环境中与同一个数据库建立多个连接?

首先,您必须将在这里和那里读到的有关SQL Server事务的内容分为两种不同的情况:本地和分布式。

本地SQL事务

  • SQL Server只允许在每个本地事务上执行一个请求。
  • 默认情况下,只有一个会话可以注册本地事务。使用sp_getbindtoken和sp_bindsession可以将多个会话注册到本地事务中。会话仍然限于在任何时间仅执行一个请求。
  • 使用多个活动结果集(MARS),一个会话可以执行多个请求。所有请求都必须注册在同一本地事务中。

分布式事务

  • 多个会话可以将其本地事务注册到单个分布式事务中。
  • 每个会话仍在本地交易中注册,但要遵守上述本地交易的所有限制
  • 分布式事务中注册的本地事务受分布式事务协调的两阶段提交的约束
  • 注册到分布式事务中的实例上的所有本地事务仍然是 独立的 本地事务,这主要意味着它们具有冲突的锁命名空间。

因此,当客户端创建.Net
TransactionScope并在此事务范围下,它在同一服务器上执行多个请求时,这些请求都是注册在分布式事务中的所有本地事务。一个简单的例子:

class Program    {        static string sqlBatch = @"set nocount on;declare @i int;set @i = 0;while @i < 100000begin    insert into test (a) values (replicate('a',100));    set @i = @i+1;end";        static void Main(string[] args)        { try {     TransactionOptions to = new TransactionOptions();     to.IsolationLevel = IsolationLevel.ReadCommitted;     using (TransactionScope scp = new TransactionScope(TransactionScopeOption.Required, to))     {         using (SqlConnection connA = new SqlConnection(Settings.Default.connString))         {  connA.Open();  using (SqlConnection connB = new SqlConnection(Settings.Default.connString))  {      connB.Open();      SqlCommand cmdA = new SqlCommand(sqlBatch, connA);      SqlCommand cmdB = new SqlCommand(sqlBatch, connB);      IAsyncResult arA = cmdA.BeginExecuteNonQuery();      IAsyncResult arB = cmdB.BeginExecuteNonQuery();      WaitHandle.WaitAll(new WaitHandle[] { arA.AsyncWaitHandle, arB.AsyncWaitHandle });      cmdA.EndExecuteNonQuery(arA);      cmdB.EndExecuteNonQuery(arB);  }         }         scp.Complete();     } } catch (Exception e) {     Console.Error.Write(e); }        }    }

创建一个虚拟测试表:

create table test (id int not null identity(1,1) primary key, a varchar(100));

并运行示例中的代码。您将看到两个请求并行执行,每个请求浪费表中的100k行,然后在事务范围完成时都提交。因此,您看到的问题与SQL
Server或TransactionScope都不相关,它们可以轻松处理您描述的情况。而且,该代码非常简单明了,并且不需要创建依赖事务,进行克隆或促进事务。

更新

使用显式线程和相关事务:

 private class ThreadState    {        public DependentTransaction Transaction {get; set;}        public EventWaitHandle Done {get; set;}        public SqlConnection Connection { get; set; }    }    static void Main(string[] args)    {        try        { TransactionOptions to = new TransactionOptions(); to.IsolationLevel = IsolationLevel.ReadCommitted; using (TransactionScope scp = new TransactionScope(TransactionScopeOption.Required, to)) {     ThreadState stateA = new ThreadState      {         Transaction = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete),         Done = new AutoResetEvent(false),         Connection = new SqlConnection(Settings.Default.connString),     };     stateA.Connection.Open();     ThreadState stateB = new ThreadState     {         Transaction = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete),         Done = new AutoResetEvent(false),         Connection = new SqlConnection(Settings.Default.connString),     };     stateB.Connection.Open();     ThreadPool.QueueUserWorkItem(new WaitCallback(Worker), stateA);     ThreadPool.QueueUserWorkItem(new WaitCallback(Worker), stateB);     WaitHandle.WaitAll(new WaitHandle[] { stateA.Done, stateB.Done });     scp.Complete();     //TODO: dispose the open connections }        }        catch (Exception e)        { Console.Error.Write(e);        }    }    private static void Worker(object args)    {        Debug.Assert(args is ThreadState);        ThreadState state = (ThreadState) args;        try        { using (TransactionScope scp = new TransactionScope(state.Transaction)) {     SqlCommand cmd = new SqlCommand(sqlBatch, state.Connection);     cmd.ExecuteNonQuery();     scp.Complete(); } state.Transaction.Complete();        }        catch (Exception e)        { Console.Error.WriteLine(e); state.Transaction.Rollback();        }        finally        { state.Done.Set();        }    }


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/410883.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号