坑人 C# MySql.Data SDK

发布于:2025-02-11 ⋅ 阅读:(39) ⋅ 点赞:(0)

一:背景

1. 讲故事

为什么说这东西比较坑人呢?是因为最近一个月接到了两个dump,都反应程序卡死无响应,最后分析下来是因为线程饥饿导致,那什么原因导致的线程饥饿呢?进一步分析发现罪魁祸首是 MySql.Data,这就让人无语了,并且反馈都是升级了MySql.Data驱动引发,接下来我们简单聊一下。

二: MySql.Data 到底怎么了

1. 祸根溯源

早期版本的 MySql.Data 访问数据库都是以同步的方式进行,比如:ExecuteReader 而不是 ExecuteReaderAsync,随着项目的升级改造需要提升MySql.Data的版本, MySql为了向前兼容保留了同步方法,下面引用最新的 MySql.Data 9.1.0 截图和参考代码如下:


// MySql.Data, Version=9.1.0.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d
// MySql.Data.MySqlClient.MySqlConnection
using System.Threading;

public override void Open()
{
	OpenAsync(execAsync: false, CancellationToken.None).GetAwaiter().GetResult();
}


// MySql.Data, Version=9.1.0.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d
// MySql.Data.MySqlClient.MySqlCommand
using System.Data;
using System.Threading;

public new MySqlDataReader ExecuteReader()
{
	return ExecuteReaderAsync(CommandBehavior.Default, execAsync: false, CancellationToken.None).GetAwaiter().GetResult();
}

public override object ExecuteScalar()
{
	return ExecuteScalarAsync(execAsync: false, CancellationToken.None).GetAwaiter().GetResult();
}

仔细看上面这段代码,不觉让人吸了一口凉气,所谓的同步方式竟然是用异步方法简单包装 而来的,这种异步混用同步的方式很容易导致线程饥饿,即线程池中已无可用线程来唤醒 GetResult() 下的 Event 事件,这个我准备后面用一篇文章详细来聊一下线程饥饿,这里用C#内功修炼训练营中的一张图来演示下.NET8 中异步在线程池中的走法。