【问题标题】:Receiving System.IO.IOException when trying to delete an entry尝试删除条目时收到 System.IO.IOException
【发布时间】:2019-03-28 11:55:41
【问题描述】:

我有一个包含 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: 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) 北 Npgsql.NpgsqlReadBuffer.c__DisplayClass31_0.d.MoveNext() 北 Npgsql.NpgsqlReadBuffer.c__DisplayClass31_0.d.MoveNext() --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- 北 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 北 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 北 Npgsql.NpgsqlConnector.c__DisplayClass161_0.d.MoveNext()

英文里面的异常是

Npgsql.NpgsqlException (0x80004005): 读取时出现异常 流 ---> System.IO.IOException: Data can't be read from the 传输连接:连接尝试失败,因为 远程站在一段时间后没有正确响应 时间,或建立连接错误,因为连接的主机 没有回应。 ---> System.Net.Sockets.SocketException:一个连接 尝试失败,因为远程站没有正确响应 一段时间后,或连接失败,因为 连接的主机没有响应 System.Net.Sockets。 Socket.Receive(Byte [] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) 在 System.Net.Sockets.NetworkStream.Read (Byte [] 缓冲区, Int32 偏移量,Int32 大小)--- 内部异常堆栈跟踪结束

在 Postgres 日志中它说:

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

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

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

【问题讨论】:

  • 您在代码中设置的超时值是多少?在代码之外运行查询需要多长时间?尝试将 commandTimeout 值设置为 0 以禁用超时
  • 将命令超时设置为 0 解决了该问题。这意味着命令返回后大约需要 30 秒。有什么办法可以调查为什么需要这么长时间?

标签: c# postgresql foreign-keys sql-delete npgsql


【解决方案1】:

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

为了解决您在 cmets 中的问题,

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

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

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

【讨论】:

    【解决方案2】:

    我的钱是在引用 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详细解释问题。

    【讨论】:

    • 非常感谢。不知道这一点,因为 FK 上的 MySQL 索引是强制性的。
    猜你喜欢
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 2012-08-09
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    相关资源
    最近更新 更多