【发布时间】: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/
基于上述,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。
现在如果它不起作用:
- 问题的哪些方面值得调查。
- 假设客户端仍然存在问题,应检查/更改哪些其他连接设置、网络设置以取得进展?
如果它确实可以始终如一地工作,那么将连接设置更改为 selectMethod=cursor 会有什么影响
- 在应用程序方面?
- 数据库端?
更新:我测试了将 selectMethod=cursor 添加到连接的应用程序。但是,它会导致与上述相同的问题。
根据与团队中其他管理员的讨论 - 此时问题可能出在 jdbc 驱动程序或操作系统上(当它尝试处理网络上的数据时)。
【问题讨论】:
-
它可能在该服务器上耗尽内存,将自身交换至死。您对
selectMethod=cursor的待定更改应该可以解决这个问题,尤其是如果您的 Java 代码不尝试记住所有数据,而是在检索到数据时对其进行处理。 -
@Andreas - 情况并非如此,因为没有过多的 GC 活动。有足够的堆大小分配给进程。未观察到 OOM。
-
我指的不是 JVM GC,而是操作系统交换。如果您为 JVM 提供的内存比操作系统可用的内存多,那么它必须交换页面。操作系统内存可能会被其他进程过载,或者如果它是一个虚拟机,主机内存可能会被其他虚拟机过载。无论哪种方式,内存交换到磁盘都会减慢处理速度,过度交换基本上会导致进程停滞,这就是我所说的“交换到死”。
-
@Andreas - 谢谢。也没有观察到操作系统交换。没有 I/O 交换的盒子有很多可用内存。
标签: java sql-server sql-server-2008