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

Receiving System.IO.IOException when trying to delete an entry

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

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

结果我收到 System.IO.Exception:

Npgsql.NpgsqlException (0x80004005): Exception while reading from stream ---> System.IO.IOException: Von der Übertragungsverbindung können keine Daten gelesen werden: Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat. ---> System.Net.Sockets.SocketException: Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat bei System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) bei System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) --- Ende der internen Ausnahmestapelüberwachung --- bei System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) bei Npgsql.NpgsqlReadBuffer.<>c__DisplayClass31_0.<g__EnsureLong|0>d.MoveNext() bei Npgsql.NpgsqlReadBuffer.<>c__DisplayClass31_0.<g__EnsureLong|0>d.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<g__ReadMessageLong|0>d.MoveNext()

在英文中,内部异常是

Npgsql.NpgsqlException (0x80004005): Exception while reading from stream ---> System.IO.IOException: Data can not be read from the transmission connection: A connection attempt failed because the remote station did not respond correctly after a certain period of time, or Established connection was faulty because the connected host did not respond. ---> System.Net.Sockets.SocketException: A connection attempt failed because the remote station did not respond correctly after a certain amount of time, or the connection made failed because the connected host did not respond to System.Net.Sockets. Socket.Receive (Byte [] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Read (Byte [] buffer, Int32 offset, Int32 size) --- End of internal exception stack trace

在 Postgres 日志中它说:

2019-03-28 12:42:15.077 CET [75060] LOG: konnte Daten vom Client nicht empfangen: unrecognized winsock error 10053

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

我认为这与 table 被如此多的外键引用有关。但我不知道如何进一步调查。

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

为了在评论中解决您的问题,

Is there any way how I can investigate why it takes such a long time?

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

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

我的钱是在引用 person.

的外键上缺少索引

如果你有这样的table:

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

并且 table 包含很多行,那么在 person 中删除的每一行都会导致在 atable 上进行顺序 table 扫描以查找匹配的行.这可能是你所有时间都花在了那里。

为所有 table 引用 person:

创建索引
CREATE INDEX ON atable (parent_id);

这将使删除速度更快。

This blog post详细说明问题。