尝试读取时 npgsql 超时

问题描述 投票:0回答:1

我有一个 C# 函数可以在 postgresql 中进行批量插入。这里发生的基本上是我有一个通用实体数组,它将被转换成一个 DataTable,然后与 BinaryImport 一起使用将数据插入到我的 postgres 数据库中。批量插入后,我从数据库读回插入的数据,并用该数据填充实体(我使用临时列来确定是否已使用最后一次批量插入插入表的一行)。

这工作得很好,直到我尝试批量插入大约 1.000.000 (978.767) 行。 (之前我只使用了〜500.000行)

大约 4 分钟后,我收到以下异常:

Npgsql.NpgsqlException:从流读取时出现异常 ---> System.TimeoutException:读取尝试期间超时

异常发生在我读回插入数据的部分的

while(reader.Read())
行。

这是我的代码:

public IEnumerable<TEntity> InsertBulkReader<TEntity>(TEntity[] entities)
{
    var table = ClientEntity.GetTable<TEntity>();
    var nonIdColumns = table.Columns.Where(column => !column.IsIdentity);
    var timeStampColumn = new Column() { Name = "TMP_BULK_INSERT_TIME_STAMP", PgType = NpgsqlDbType.TimestampTz };
    //Adding timeStampColumn to the actual table

    using (var connection = new NpgsqlConnection(base.ConnectionString))
    {

        connection.Open();

        using (var transactionScope = TransactionScopeUtil.Create(Transaction.Current))
        {
            var cmd = $"COPY {table.FullName()} ({string.Join(",", nonIdColumns.Concat(new List<Column>() { timeStampColumn }).Select(column => column.Name))}) FROM STDIN BINARY";

            using (var writer = connection.BeginBinaryImport(cmd))
            {
                writer.Timeout = TimeSpan.FromMinutes(10);

                foreach (DataRow row in dataTable.Rows)
                {
                    writer.StartRow();
                    foreach (var column in nonIdColumns)
                    {
                        if (column.PgType == NpgsqlDbType.Unknown || column.PgType == (NpgsqlDbType.Array | NpgsqlDbType.Unknown))
                        {
                            writer.Write(row[column.Name]);
                        }
                        else
                        {
                            writer.Write(row[column.Name], column.PgType);
                        }
                    }
                    writer.Write(row[timeStampColumn.Name], timeStampColumn.PgType);
                }
                writer.Complete();
                writer.Close();
            }

            using (var command = connection.CreateCommand())
            {
                command.CommandTimeout = 0;
        
                command.CommandText = $"SELECT * FROM {table.FullName()} WHERE {timeStampColumn.Name} >= @TIMESTAMP";
                command.Parameters.Add(new NpgsqlParameter() { ParameterName = "TIMESTAMP", Value = timeStampBeforeInsert, });

                using (var reader = command.ExecuteReader())
                {
            
                    while (reader.Read()) //Here the exception is thrown
                    {
                        var entity = new TEntity();

                        foreach (var column in table.Columns)
                        {
                            //Populate entity with values from reader
                        }

                        result.Add(entity);
                    }
                }
            }

            transactionScope.Complete();
            transactionScope.Dispose();
        }
    }
    return result;
}

我在连接字符串中尝试了以下选项:

CommandTimeout = 0;
InternalCommandTimeout = 0;
KeepAlive = 60 * 10;

我还添加了

command.CommandTimeOut = 0;
到与
ExecuteReader()
一起使用来读回数据的命令。

我进一步检查了postgresql服务器的STATMENT_TIMEOUT,以确保服务器本身没有超时。

显示 STATEMENT_TIMEOUT => "0"

如果我在服务器上执行类似

select pg_wait(60 * 10)
的操作,则不会出现错误,问题一定出在我的代码上。我还能做什么来跟踪问题?

c# postgresql timeout npgsql
1个回答
0
投票

我已经执行了收到异常时正在运行的查询,并在我的 phpstorm 数据库插件中执行了它。两秒后结果显示。但它是分页的,所以我点击了“到最后一页”按钮。然后 30 秒后我收到以下错误

[2023-09-28 15:42:35] Error unmarshaling return header; nested exception is: 
[2023-09-28 15:42:35] java.net.SocketException: Connection reset

之后我第二次尝试,又出现了错误

[2023-09-28 15:44:25] Database client process needs more memory to perform the request. 
[2023-09-28 15:44:25] To configure settings, open 'development_db@localhost' data source properties, go to the 'Advanced' tab, and add 
[2023-09-28 15:44:25] '-XmxNNNm' to the 'VM options' field, where NNN is the number of megabytes (for example, '-Xmx2048m').

按照上面消息中所述将内存增加到 2048mb 后,错误消失了。

© www.soinside.com 2019 - 2024. All rights reserved.