【问题标题】:Microsoft SQL Server - Query with huge results, causes ASYNC_NETWORK_IO wait issueMicrosoft SQL Server - 查询结果巨大,导致 ASYNC_NETWORK_IO 等待问题
【发布时间】:2017-08-17 20:27:18
【问题描述】:

我有一个 Java 应用程序从 Microsoft SQL Server(Microsoft SQL Server 2008 R2 (SP3))请求大约 240 万条记录

应用程序在所有主机上运行良好,除了一台。在此主机上,应用程序能够在某些情况下检索数据。但在其他一些情况下,它会挂起。

监控 MS Sql 服务器表明与查询关联的 SPID 处于 ASYNC_NETWORK_IO 等待状态。

网上有几个链接在谈论它。
https://blogs.msdn.microsoft.com/joesack/2009/01/08/troubleshooting-async_network_io-networkio/

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/6db233d5-8892-4f8a-88c7-b72d0fc59ca9/very-high-asyncnetworkio?forum=sqldatabaseengine

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/1df2cab8-33ca-4870-9daf-ed333a64630c/network-packet-size-and-delay-by-sql-server-sending-data-to-client?forum=sqldatabaseengine

基于上述,ASYNC_NETWORK_IO 意味着两件事: 1.申请处理结果慢 2. 应用程序和数据库之间的网络存在一些问题。

对于上面的#1,我们使用tcpdumps分析发现,在查询进入ASYNC_NETWORK_IO状态的情况下,应用服务器的tcp连接的窗口大小在0到一个小数之间振荡,最终卡在0 . 根据更多的分析,DB和应用程序之间的防火墙相关的方面也大多被排除在外。

所以我盯着#2,无法理解可能出了什么问题。更令人困惑的是,相同的代码已经在类似的数据负载下运行了一年多。它在其他主机上也能正常运行。

使用的 JDBC 驱动程序是 sqljdbc4-4.0.jar。 默认情况下,它具有自适应缓冲功能,可以在后台执行操作以减少应用程序资源。 我们使用默认的 128 提取大小(我认为这不是一个好的)。

所以我将尝试覆盖默认的自适应缓冲行为,尽管 MS 文档建议对大型结果集进行自适应缓冲是件好事。

我将更改连接设置以使用 selectMethod=cursor。 并将 fetchSize 更改为 1024。

现在如果它不起作用:

  1. 问题的哪些方面值得调查。
  2. 假设客户端仍然存在问题,应检查/更改哪些其他连接设置、网络设置以取得进展?

如果它确实可以始终如一地工作,那么将连接设置更改为 selectMethod=cursor 会有什么影响

  1. 在应用程序方面?
  2. 数据库端?

更新:我测试了将 selectMethod=cursor 添加到连接的应用程序。但是,它会导致与上述相同的问题。

根据与团队中其他管理员的讨论 - 此时问题可能出在 jdbc 驱动程序或操作系统上(当它尝试处理网络上的数据时)。

【问题讨论】:

  • 它可能在该服务器上耗尽内存,将自身交换至死。您对 selectMethod=cursor 的待定更改应该可以解决这个问题,尤其是如果您的 Java 代码不尝试记住所有数据,而是在检索到数据时对其进行处理。
  • @Andreas - 情况并非如此,因为没有过多的 GC 活动。有足够的堆大小分配给进程。未观察到 OOM。
  • 我指的不是 JVM GC,而是操作系统交换。如果您为 JVM 提供的内存比操作系统可用的内存多,那么它必须交换页面。操作系统内存可能会被其他进程过载,或者如果它是一个虚拟机,主机内存可能会被其他虚拟机过载。无论哪种方式,内存交换到磁盘都会减慢处理速度,过度交换基本上会导致进程停滞,这就是我所说的“交换到死”。
  • @Andreas - 谢谢。也没有观察到操作系统交换。没有 I/O 交换的盒子有很多可用内存。

标签: java sql-server sql-server-2008


【解决方案1】:

在与系统管理员、网络管理员和数据库管理员进行大量讨论后 - 一致认为在操作系统的某个位置 -> 应用程序堆栈中,来自网络的数据没有得到处理。与此同时,我们测试了一个解决方案,我们分解查询以返回更小的结果。所以我们将其分解为 5 个查询,每个查询返回大约 50 万条记录。

现在,当我们按顺序运行这些查询时,我们仍然遇到了同样的问题。

但是,当我们并行运行查询时,它总是成功的。

鉴于解决方案始终有效,我们不再费心去寻找问题的根本原因。

另一方面,运行该应用程序的硬件和软件也已过时。它运行的是 Red Hat 5。所以,它很可能需要为此做点什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 2013-04-01
    • 2019-04-02
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    相关资源
    最近更新 更多