【问题标题】:Asynchronous processing in SQL Server vs. .NET Asynchronous processingSQL Server 中的异步处理与 .NET 异步处理
【发布时间】:2009-11-14 02:28:27
【问题描述】:

在 SQL Server 中使用异步处理相对于 .NET 异步处理有什么优势?他们不一样吗?我很难理解在 SQL Server 中使用异步处理而不是 .NET APM 有什么好处。我可以轻松地将 SQL 调用包装在 lambda 表达式中并执行 BeginInvoke(...)。

有人可以帮我区分两者的区别和好处吗?

【问题讨论】:

    标签: .net sql-server asynchronous


    【解决方案1】:

    .NET 异步处理 (BeginInvoke(...)) 的问题在于,所有这些都在分离一个线程以同步处理代码。一个 5 分钟的查询将占用一个线程 5 分钟,阻塞(即在大约 99% 的时间里什么都不做),同时在远程端计算结果。在压力下(一次很多查询),这将耗尽线程池,使所有线程处于阻塞状态。线程池将变得无响应,新的工作请求将遭受很大的延迟,等待线程池启动额外的线程。这不是线程池的预期用途,因为它被设计为期望它被要求完成的任务是短暂的和非阻塞的。

    使用 Begin/EndAction APM 对,可以以非阻塞方式调用相同的操作,并且只有当结果通过 IO 完成端口返回时,它才会作为工作项在线程池中排队。您的任何线程都不会在此期间被占用,并且在处理排队的响应时,数据可用,这意味着用户代码不会阻塞 IO,并且可以快速完成......更有效地使用线程池,它可以扩展到更多的客户端请求,而无需为每个未完成的操作增加线程成本。

    【讨论】:

      【解决方案2】:

      如前面的答案所述,BeginInvoke 使用 .NET 线程。然而,同样重要的是,线程来自 ASP.NET 线程池,因此它与客户端竞争非常有限的线程资源。 ThreadPool.QueueUserWorkItem() 也是如此。

      SqlClient 异步调用需要启用 async=true 的 SqlConnection。该模式需要更多的网络开销(这就是默认情况下不启用它的原因),但它不会消耗 .NET 线程池中的线程。相反,它使用异步 I/O。

      后一种方法的优势在于它的可扩展性更高。您可以通过这种方式同时处理成百上千个请求,而每次调用线程的开销会非常大。另外,您会很快消耗整个 ASP.NET 线程池(默认情况下它最多只有大约 12 个线程)。

      【讨论】:

        【解决方案3】:

        .Net BeginInvoke 只是将执行推迟到另一个线程。这总是比同步调用慢并消耗额外的资源。使用它的唯一原因是释放调用者上下文以进行其他操作(例如,将 HTTP 请求的结果返回给客户端)。

        SqlClient异步方法,当连接上的AsynchronousProcessing属性设置为true并使用SqlCommand的BeginExecute方法时,才是真正的异步。 SQL 命令发布到网络通信通道,并在服务器返回结果时调用完成。

        从可靠性的角度来看,尽管这些方法都没有用。它们都依赖客户端进程一直待到调用完成,否则 SQL Server 会看到客户端断开连接并放弃处理,回滚任何中间工作。考虑一个接受 HTTP 请求、提交“异步”支付处理并返回响应的 ASP 应用程序。没有任何方法可以保证提交的工作会真正发生。

        对于处理需要可靠性保证的情况,解决方案是将服务器上的工作排队,提交然后继续,依靠 SQL Server 自己的异步处理能力。这是一种即使在存在客户端断开连接、ASP 进程“回收”、SQL Server 镜像或集群故障转移、硬件灾难恢复以及几乎任何你可以扔给它的情况下也能保证处理的方法,因为它是一种事务性持久的提交方式异步处理请求。示例见Asynchronous Procedure Execution。

        【讨论】:

          【解决方案4】:

          从这篇文章SQL Server 2008 Books Online (October 2009) - Performing Asynchronous Operations,我引用:

          异步处理启用 立即返回的方法 在调用线程上阻塞。这 允许大部分的权力和 多线程的灵活性,无需 要求开发者明确 创建线程或句柄 同步。

          如果您已经明确地创建了这些线程并处理了同步,那么您可能不会发现太大的区别。

          【讨论】:

          • 我认为他的意思是“为什么使用数据提供者 'BeginExecute___()/EndExecute____()' 而不是将它们包装在委托中。
          【解决方案5】:

          如果您的意思是“为什么要使用数据提供程序 BeginExecute___()/EndExecute____() 方法而不是在委托中包装普通的 Execute____(),我怀疑答案是当他们第一次为 .Net 1.0 设计 ado.net 提供程序模型时,在委托中包装一些东西并异步调用它并不是那么简单。

          其他可能的原因是这与它们为原始 .Net 更新或包装的旧代码的工作方式相匹配,或者内置方法允许您轻松检查任何返回的异常

          【讨论】:

          • 也许他们 .NET 团队的 MS 人员更了解:P
          • SqlClient 的 BeginExecute/EndExecute 如果连接配置正确,则使用异步 IO,它们不仅仅是普通的委托异步调用。
          猜你喜欢
          • 2013-07-04
          • 2019-08-29
          • 1970-01-01
          • 1970-01-01
          • 2012-08-23
          • 2022-01-12
          • 2017-06-03
          • 2011-05-30
          • 2016-04-29
          相关资源
          最近更新 更多