尝试删除条目时接收System.IO.IOException

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

我有一个包含60个表的数据库。一个是表person,由大量其他表(约40个)引用,主要使用ON DELETE CASCADE ON UPDATE CASCADE

使用Npgsql,我尝试运行以下命令:DELETE FROM person WHERE id = @PersonId

结果我收到一个System.IO.Exception:

Npgsql.NpgsqlException(0X80004005):异常而从流读取---> System.IO.IOException:没有从传输链路可以读取数据:连接尝试失败,因为连接的方没有正确一段时间后做出反应,或建立的连接有问题,因为连接的主机没有响应。 ---> System.Net.Sockets.SocketException:A连接尝试失败,因为连接的方没有正确一段时间后响应或已建立的连接失败,因为连接的主机没有在的System.Net.Sockets回应。 Socket.Receive(字节[]缓冲液,的Int32偏移量,大小的Int32,的SocketFlags的SocketFlags)在System.Net.Sockets.NetworkStream.Read(字节[]缓冲液,的Int32偏移的Int32大小)---的异常堆栈跟踪的端---在Npgsql.NpgsqlReadBuffer d.MoveNext()<> c__DisplayClass31_0 |。(偏移字节[]缓冲液,的Int32,的Int32大小)在System.Net.Sockets.NetworkStream.Read在Npgsql.NpgsqlReadBuffer <> c__DisplayClass31_0 <0 g__EnsureLong> ... <g__EnsureLong | 0> d.MoveNext()---从以前的地方除外在System.Runtime.CompilerServices抛出---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)堆栈跟踪结束。 TaskAwaiter.HandleNonSuccessAndDebuggerNotification在Npgsql.NpgsqlConnector(任务的任务)<> c__DisplayClass161_0 .. <G__ReadMessageLong | 0> d.MoveNext()

在英语中,内在的例外是

Npgsql.NpgsqlException(0x80004005):从流中读取时出现异常---> System.IO.IOException:无法从传输连接读取数据:连接尝试失败,因为远程站在一段时间后没有正确响应,或已建立的连接有问题,因为连接的主机没有响应。 ---> System.Net.Sockets.SocketException:连接尝试失败,因为远程工作站在一段时间后没有正确响应,或连接失败,因为连接的主机没有响应System.Net.Sockets。 System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)的Socket.Receive(Byte []缓冲区,Int32偏移量,Int32大小,SocketFlags socketFlags)---内部异常堆栈跟踪结束

在Postgres日志中它说:

2019-03-28 12:42:15.077 CET [75060]日志:无法接收客户端数据:无法识别的winsock错误10053

我认为它不是死锁,因为日志中没有死锁消息。

我认为这与该表被许多外键引用的事实有关。但我不知道如何进一步调查。

c# postgresql foreign-keys sql-delete npgsql
2个回答
1
投票

我的钱是在引用person的外键上缺少索引。

如果您有这样的表格:

CREATE TABLE atable (
   id bigint PRIMARY KEY,
   parent_id bigint NOT NULL
      REFERENCING parent ON DELETE CASCADE
);

并且该表包含许多行,然后在person中删除的每一行都将导致atable上的顺序表扫描以查找匹配的行。那可能就是你花费的所有时间。

在引用person的所有表上创建索引:

CREATE INDEX ON atable (parent_id);

这将使删除更快。

This blog post详细解释了这个问题。


3
投票

根据例外,此问题与长时间运行的脚本的超时有关。您没有包含代码示例,因此我无法专门提供增加此语法的语法,但设置commandTimeout = 0将禁用超时并将解决问题。

要在评论中解决您的问题,

有什么方法可以调查为什么需要这么长时间?

它可能只是删除了大量的记录。您应该在C#之外运行查询,以确保在将代码插入代码之前优化查询。

删除大量记录可能需要一段时间,您应该查看truncate或其他一些清除设计,例如转储到临时表等。

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