【问题标题】:MySql query causes exception: System.Net.Security._SslStream.ProcessReadMySql 查询导致异常:System.Net.Security._SslStream.ProcessRead
【发布时间】:2020-01-09 11:49:52
【问题描述】:

我的应用程序由于此异常而崩溃:

Exception Info: System.NotSupportedException
   at System.Net.Security._SslStream.ProcessRead(Byte[], Int32, Int32, System.Net.AsyncProtocolRequest)
   at System.Net.Security.SslStream.Read(Byte[], Int32, Int32)
   at MySql.Data.MySqlClient.TimedStream.Read(Byte[], Int32, Int32)
   at MySql.Data.MySqlClient.MySqlStream.ReadFully(System.IO.Stream, Byte[], Int32, Int32)
   at MySql.Data.MySqlClient.MySqlStream.LoadPacket()
   at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32 ByRef, Int64 ByRef)
   at MySql.Data.MySqlClient.Driver.GetResult(Int32, Int32 ByRef, Int64 ByRef)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32, Boolean)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlDataReader.Close()
   at MySql.Data.MySqlClient.MySqlConnection.Close()
   at MySql.Data.MySqlClient.MySqlConnection.Dispose(Boolean)
   at MySql.Data.MySqlClient.MySqlConnection.Finalize()

我已经尝试升级到最新的框架,并下载了最新版本的 MySql.Data 文件。

这就是我的一种查询方法的样子。其他查询方法遵循相同的结构。

public static long InsertReturnInsertedAutoIncID(string queryStr, string[,] Parameters)
{
    int attempts = 0;
    do
    {
        try
        {
            attempts++;
            long autoIncID;
            using (MySqlConnection dbObj = new MySqlConnection(connectionToDBstring))
            {
                dbObj.Open();
                using (MySqlCommand query = new MySqlCommand(queryStr, dbObj))
                {
                    // Add parameters to query (as we don't want to concatinate)
                    for (int i = 0; i < Parameters.GetLength(0); i++)
                    {
                        query.Parameters.AddWithValue(Parameters[i, 0], Parameters[i, 1]);

                    }
                    query.ExecuteNonQuery();
                    autoIncID = query.LastInsertedId;
                }
            }
            return autoIncID;
        }
        catch (Exception ex)
        {
            Logger.Log.Error(ex.ToString());
            if (attempts >= maxAttempts)
            {
                return -1;
            }
            System.Threading.Thread.Sleep(200);
        }
    } while (true);
}

我的应用程序中运行着许多线程(任务)来查询数据库。没有使用锁,因为线程不应该被搁置太久。这个问题很少发生(比如每 7 天左右)。我希望这个异常根本不会发生,但是如果我可以忽略也可以的异常,那么我会重试查询。问题是这个异常导致我的应用程序停止工作(因为应用程序正在获取“应用程序已停止工作”窗口。)

【问题讨论】:

  • 尝试将异常处理程序放在“使用”中。 using 有自己的处理程序,然后代码返回并且永远不会看到您的 while 循环。
  • 嗨。我试图在两个“使用”块中产生异常。当发生异常时,下一个执行的行是 catch 块。这是正确的行为。因此,我不确定在“使用”块中添加异常处理程序有何帮助。
  • 请发布 A) SHOW GLOBAL STATUS LIKE '%thread%'; 的 TEXT 结果和 B) 显示全局变量,例如 '%thread%';和 C) SHOW GLOBAL STATUS LIKE 'com_stmt%';

标签: c# mysql ssl exception


【解决方案1】:

异常最终来自MySql.Data.MySqlClient.MySqlConnection.Finalize()。这意味着您的 MySqlConnection 对象没有被正确清理(通过 usingDisposeClose),因此正在被 .NET 垃圾收集器运行的最终化清理。

请注意,MySql.Data 通过清理其终结器中的托管资源违反了 .NET 终结最佳实践。这是明确禁止的,因为“未定义垃圾收集器在终结期间销毁托管对象的顺序”。很有可能NotSupportedException 被抛出,因为SslStream 的资源在MySqlConnection 尝试关闭连接时已经完成。

不幸的是,终结器中未处理的异常会中止应用程序(这是最佳实践要求在终结器中完成尽可能少的工作的另一个原因)。

我的建议是审核您的代码并确保每个 MySqlConnection 都被正确清理。最安全的方法是使用 using 块,如示例代码所示。但似乎有一些其他实例没有使用这种模式。

其次,您可以切换到MySqlConnector。这是一个替代 OSS MySQL ADO.NET 库,它遵循所有 .NET 最佳实践(并且不包含终结器)。使用这个库时你仍然应该清理你的连接(否则你会有连接池泄漏),但它不会在后台抛出未处理的异常。

【讨论】:

  • 嗨。谢谢回复。我目前正在我拥有的每个 using{} 语句中测试 try{} catch{}。在这篇文章中推荐了它:stackoverflow.com/questions/10193674/…。 jdweng 还评论说这可以解决问题。由于这个问题很难复制并且很少发生,我无法确定这是否能解决问题,直到至少 2 周的测试。您是否也认为这会解决我的问题,或者您是否建议已经切换到 MySqlConnector?
  • @Chillychillx 添加try/catch 块本身不会解决这个问题,因为关闭每个MySqlConnection 无济于事。因为异常调用堆栈清楚地表明 MySqlConnection 正在被最终确定,所以 必须 在某处创建和打开 MySqlConnection 对象而不被关闭或处置。这就是我试图解决此问题的方法。
  • @Chillychillx FWIW,有一些工具可以监控您的应用程序并查找未处理的对象;然后,他们可以向您展示其分配的完整调用堆栈,这通常可以帮助快速缩小范围。 .NET Memory Profiler 就是这样一种工具;我相信 JetBrains dotTrace 也可以做到这一点。如果您能够在开发机器上运行此应用程序(在生产负载下)并使用其中一种工具对其进行诊断,那么这可能是解决此问题的最快方法。
猜你喜欢
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 2011-06-08
  • 1970-01-01
相关资源
最近更新 更多