.NET Framework 4.0中Npgsql.dll抛出System.IO.IOException求助排查
异常排查:Npgsql.dll中System.IO.IOException异常分析
问题背景
项目基于.NET Framework 4.0,执行操作时调试控制台提示Npgsql.dll中引发了System.IO.IOException异常,完整错误日志如下:
System.IO.IOException: Data cannot be read from the transport connection: The remote host forcibly terminated the existing connection. ---> System.Net.Sockets.SocketException: The remote host forcibly terminated an existing connection в System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) --- --- в System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) в System.IO.BufferedStream.ReadByte() в Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext() в C:\projects\Npgsql2\src\Npgsql\NpgsqlState.cs:line 672 в Npgsql.NpgsqlState.IterateThroughAllResponses(IEnumerable`1 ienum) в C:\projects\Npgsql2\src\Npgsql\NpgsqlState.cs:line 326 в Npgsql.NpgsqlConnectedState.Startup(NpgsqlConnector context) в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnectedState.cs:line 53 в Npgsql.NpgsqlConnector.Open() в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnector.cs:line 687 в Npgsql.NpgsqlConnectorPool.GetPooledConnector(NpgsqlConnection Connection) в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnectorPool.cs:line 447 в Npgsql.NpgsqlConnectorPool.RequestPooledConnectorInternal(NpgsqlConnection Connection) в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnectorPool.cs:line 255 в Npgsql.NpgsqlConnectorPool.RequestPooledConnector(NpgsqlConnection Connection) в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnectorPool.cs:line 197 в Npgsql.NpgsqlConnectorPool.RequestConnector(NpgsqlConnection Connection) в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnectorPool.cs:line 181 в Npgsql.NpgsqlConnection.Open() в C:\projects\Npgsql2\src\Npgsql\NpgsqlConnection.cs:line 536 в ByndyuSoft.Gis.Web.Application.Infrastructure.Postgress.PostgressAbstract.Execute(NpgsqlCommand command, PostgresCommandTypes pgCommandType) в C:\Users\***\Documents\***\***\sources\Web.Application\Infrastructure\Postgress\PostgressAbstract.cs:line 33
相关代码(PostgressAbstract.cs)
using NLog; using Npgsql; using System; using System.Collections.Generic; using System.Configuration; using System.Data; namespace Example { public abstract class PostgressAbstract { private static Logger _logger = LogManager.GetCurrentClassLogger(); protected string Error { get; private set; } private object Result { get; set; } protected string ConnectName { private get; set; } protected PostgressAbstract(string connectName) { ConnectName = connectName; } protected object Execute(NpgsqlCommand command, PostgresCommandTypes pgCommandType) { using (var thisConn = new NpgsqlConnection("Server=***;Port=***;Userid=***;Password=***;Protocol=***;SSL=***;Timeout=***;SslMode=***;Database=***;")) { command.Connection = thisConn; if (pgCommandType == PostgresCommandTypes.Scale) { try { thisConn.Open(); Result = command.ExecuteScalar(); } catch (Exception ex) { Error = ex.ToString(); Result = null; } finally { thisConn.Close(); } } else if (pgCommandType == PostgresCommandTypes.Table) { try { command.Connection.Open(); var da = new NpgsqlDataAdapter(command); var ds = new DataSet(); da.Fill(ds); if (ds.Tables.Count > 0) { Result = ds.Tables[0]; } } catch (Exception ex) { Error = ex.ToString(); _logger.Error(ex.ToString()); Result = null; } finally { thisConn.Close(); } } return Result; } } protected NpgsqlCommand CreateProcedureCommand(string nameFunction, IEnumerable<PostgresParameters> args) { var command = new NpgsqlCommand(nameFunction) { CommandType = CommandType.StoredProcedure }; foreach (var par in args) { var parameter = command.CreateParameter(); parameter.ParameterName = par.Name; parameter.DbType = par.Type; parameter.Value = par.Value; command.Parameters.Add(parameter); } return command; } } }
异常成因分析
- 数据库服务器主动断开连接:错误核心是远程主机(PostgreSQL服务器)强制终止连接,常见场景包括:
- 服务器配置了较短的
idle_in_transaction_session_timeout或statement_timeout,连接闲置超时或语句执行超时被服务器主动断开; - 服务器资源耗尽(内存、CPU不足),系统主动清理占用资源的连接;
- 数据库服务器重启、网络中断后恢复,原有连接已失效但未被客户端感知。
- 服务器配置了较短的
- Npgsql连接池存在失效连接:错误栈显示从连接池获取连接时出错,连接池中可能存在已被服务器断开的无效连接,客户端尝试使用这类连接时触发异常。
- 连接字符串配置不合理:检查以下参数是否匹配服务器要求:
Timeout设置过短,导致连接建立过程中超时;SslMode与服务器SSL配置不匹配,握手失败导致连接被断开;Protocol版本与PostgreSQL服务器版本不兼容,连接协商失败。
- 代码连接管理的潜在问题:
- 未添加连接重试逻辑,遇到临时网络波动或服务器短时间不可用的情况,直接抛出异常;
- 虽然使用
using包裹连接,但如果连接池返回无效连接,打开操作会直接触发异常。
内容的提问来源于stack exchange,提问作者Twinkles
相关产品推荐
相关产品推荐

