【问题标题】:postgres, server closed the connection unexpectedly via VBSpostgres,服务器通过 VBS 意外关闭了连接
【发布时间】:2017-09-28 13:38:33
【问题描述】:

我收到此错误:

“服务器意外关闭连接这可能意味着服务器在处理请求之前或期间异常终止。”

使用这个 VBScript (vbs):

dim cn
set cn = CreateObject("ADODB.Connection")  
cn.ConnectionString= "DSN=dsn_name_here" 
cn.open 
cn.CommandTimeout = 28800

cn.execute("vacuum analyze fund_data;")
cn.execute("vacuum analyze daily_data;") '<-- error here

这条线运行良好: cn.execute("vacuum analyze fund_data;")

但这行错误: cn.execute("vacuum analyze daily_data;")

我想我知道为什么以及如何预防它,但我想知道是否有更好的解决方案以及如何确定根本原因

我认为原因与缺乏资源有关。 daily_data 是一个比 fund_data 大得多的表,当这个错误时,我还有另外两个相当大的查询正在运行,其中一个也因同样的错误而失败。我在想太多事情了,但我如何确定根本原因?是磁盘空间不足吗? (我知道我们没有足够的内存,所以我认为查询正在写入磁盘。我们正在讨论升级我们的服务器,但我想了解并能够诊断。)有没有办法确定根?

我认为解决方案是对查询进行不同的计时,这样它们就不会同时运行。那里的问题是,因为我们缺乏资源,所以一切都运行得很慢,而且每天的日程安排都被超额预订了,我需要偷偷溜进一些vacuums。从脚本的角度(或 DBA 的角度)有没有更好的方法没有进入实际查询的细节?

为什么 postgres 不只是减慢或锁定查询而不是终止它们?还是有其他事情没有发生?

PS - 如果更合适,我会将这个问题移至 SO DBA 网站,但我想我会先尝试从脚本角度提出问题。

EDIT1:我正在运行的内容:

来自 pgadmin:

select version();
PostgreSQL 9.6.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit

从安装 PostgreSQL 的虚拟服务器的终端:

lsb_release -a
LSB Version: n/a
Distributor ID: SUSE LINUX
Description: SUSE Linux Enterprise Server 12
Release: 12
Codename: 12

uname -r
3.12.28-4-default

VBScript 在 Windows 7 笔记本电脑上运行。

我有什么问题吗?

EDIT2:

我在这里更新了我的 odbc 驱动程序: https://www.postgresql.org/ftp/odbc/versions/msi/

他们现在有了(没有注意到我在更新之前有什么):

%WINDIR%\SysWOW64\odbcad32.exe Drivers 选项卡包含 PostgreSQL ANSI(x64) 9.06.05.00 和 PostgreSQL Unicode(x64) 9.06.05.00

%WINDIR%\SysWOW64\odbcad32.exe Drivers 选项卡具有 PostgreSQL ANSI 9.06.05.00 和 PostgreSQL Unicode 9.06.05.00

使用新驱动程序重新启动笔记本电脑,并通过以下良好但略微不准确的链接为我的服务器日志文件设置一个外部数据表: https://dba.stackexchange.com/questions/153904/pgadmin-4-server-status-view-log-file

...所以我明天可以提供一些服务器日志。

编辑 3:

除了 EDIT 2,我重新启动了服务器。

我今天早上成功创建了错误。和以前一样。服务器日志没有显示任何关于 vacuum 查询的信息:

select * from postgres_log 
where query like '%vacuum%'

但是,像往常一样,vacuum 和另一个同时“错误”的查询仍然显示在 pg_stat_activity

select pid,query,state,wait_event,* from pg_stat_activity where state <> 'idle'

“错误”是指我在原始问题中遇到错误,但查询似乎仍在运行。至少真空确实如此。

最终,如果我检查我的vacuums,它会在last_vacuum 下完成真空。我可以通过此查询中的日期看到这一点:

 select relname,last_vacuum, last_autovacuum, last_analyze, last_autoanalyze from pg_stat_user_tables order by relname;

所以我认为服务器认为查询很好。对我来说,这似乎是剧本中的某些内容。顺便说一下,vacuum 正在运行,自查询开始后状态没有变化,但此查询通常会完成。

这可能是什么?您还需要什么其他信息?

另外,我认为这并不重要,但在发生错误时,我同时从 VBA 和 VBS 运行查询。

编辑 4:

经过时间调查:

 select * from postgres_log where session_start_time > '2017-09-29 06:00:00'

我发现 5 个服务器日志“使用过时的统计信息而不是当前的统计信息,因为统计信息收集器没有响应”。

注意:在出现问题期间,服务器没有记录任何其他内容。

我快速搜索了那个错误,我发现了这个: https://www.postgresql.org/message-id/1457523467.24545.43.camel%402ndquadrant.com

听起来像是我的“I/O 系统过载”?

编辑 5:

我不确定这是否重要,但大约在这个时候,我们遇到了一些一般的 LAN 缓慢/消息传递问题。

具体来说,这是一个完全不同的进程,它使用与我上面最初的问题相同的 LAN 运行。详情: https://serverfault.com/questions/873296/saving-large-excel-files-to-network-drive-locks-on-saving-progress-bar-popup

这有关系吗?

【问题讨论】:

  • 老实说,VBScript 代码不是很好,你创建了一个ADODB.Command 对象,设置超时然后永远不要使用它,而是使用ADODB.Connection 对象的Execute() 方法触发查询. cmDB 对象在上面的代码中什么都不做。不过,这不会导致 PostgreSQL 出现问题。
  • 谢谢@Lankymart。我现在看到了。这是需要清理的遗留代码。我将在脚本中进行更改。我也应该在问题中清理它吗?我还更新了 odbc 驱动程序,现在正在测试它。
  • @Lankymart - 端口在系统 DSN 配置中定义,如下所示(来自我在网上找到的图片......这不是我的配置):vasco.com/images/120223-img-1_tcm42-55377.PNG
  • 我以前在不可靠的网络上看到过这种情况。当客户端说服务器关闭连接时服务器没有记录任何内容,这是因为服务器没有关闭连接。别的东西做了。服务器很高兴地没有意识到并将继续执行正在处理的查询,并且只有在尝试发送结果时才发现它与客户端失去了连接。因此,服务器端错误可能比客户端错误晚得多。

标签: postgresql performance vbscript server monitoring


【解决方案1】:

正如 Eelke 在 cmets 中提到的,问题在于缺乏网络可靠性。由于网络中断而中断/中断的连接(在这种情况下是通过 vbs 建立的)可能会导致程序中出现此类错误(在这种情况下是 vbscript),但不会立即产生任何服务器端错误:

“服务器意外关闭连接这可能意味着服务器在处理请求之前或期间异常终止。”

解决方案:让网络更可靠

【讨论】:

    【解决方案2】:

    也许设置以下配置参数是一种解决方案

    tcp_keepalives_idle(整数)

    指定不活动的秒数,在此之后 TCP 应向客户端发送保持活动消息。值 0 使用系统默认值。此参数仅在支持 TCP_KEEPIDLE 或等效套接字选项的系统和 Windows 上受支持;在其他系统上,它必须为零。在通过 Unix 域套接字连接的会话中,此参数被忽略并始终读取为零。

    tcp_keepalives_interval(整数)

    指定客户端未确认的 TCP keepalive 消息应重新传输的秒数。值 0 使用系统默认值。此参数仅在支持 TCP_KEEPINTVL 或等效套接字选项的系统和 Windows 上受支持;在其他系统上,它必须为零。在通过 Unix 域套接字连接的会话中,此参数被忽略并始终读取为零。

    tcp_keepalives_count(整数)

    指定在服务器与客户端的连接被视为死亡之前可以丢失的 TCP keepalive 数量。值 0 使用系统默认值。此参数仅在支持 TCP_KEEPCNT 或等效套接字选项的系统上受支持;在其他系统上,它必须为零。在通过 Unix 域套接字连接的会话中,此参数被忽略并始终读取为零。

    【讨论】:

      【解决方案3】:

      为我解决这个问题的解决方案是将 ODBC 连接中的此设置从默认值 1 更改为 0:

      UseServerSidePrepare=0

      【讨论】:

        猜你喜欢
        • 2017-03-31
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 1970-01-01
        • 2018-02-20
        • 2012-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多