MySql.Data 6.9.11.0连接MySQL5.7.29出现GetResult空引用异常咨询
问题根因确认
该空引用异常属于 MySql.Data.dll 6.9.11.0 版本的已知原生缺陷,与业务查询逻辑无直接关联。
异常堆栈显示错误最终在 MySqlDataReader.Finalize() 析构流程中触发,由GC线程抛出未处理异常导致进程终止,具体触发逻辑如下:
- 6.9.11.0 版本对MySQL 5.7及以上版本的通信协议兼容存在设计漏洞,当连接提前关闭、SQL返回多结果集时,MySqlDataReader内部持有的NativeDriver实例会被提前置空
- 该版本在NativeDriver的 GetResult 方法中未做空对象有效性判断,析构流程调用该方法时就会抛出 NullReferenceException
- 由于异常发生在GC的Finalize执行线程,无法被业务代码的常规try-catch捕获,最终直接导致整个进程终止。
可行解决方向
- 优先升级依赖版本:将MySql.Data从 6.9.11.0 升级到同分支的 6.9.12 及以上修复版本,或是直接适配8.0.x系列稳定版(升级时注意同步调整连接字符串的SSL模式、认证插件配置,适配MySQL 5.7/8.0的默认规则),官方在后续版本中已经补充了NativeDriver的空判断逻辑,从根源上修复了该析构崩溃问题。
- 调整资源释放逻辑:如果因为项目依赖锁定无法升级版本,需要修正现有代码的资源释放流程,不要在
da.Fill()完成后手动调用conn.Close(),同时将所有涉及的数据库访问对象纳入using作用域,保证资源按照正常的Dispose链路回收,避免将Reader对象丢给GC走Finalize流程触发异常。修正后的参考代码如下:
public DataSet ExecuteQuery(string connectionString, CommandType cmdType, string cmdText, MySqlParameter[] cmdParms) { using (MySqlConnection conn = new MySqlConnection(connectionString)) using (MySqlCommand cmd = new MySqlCommand()) { PrepareCommand(conn, null, cmd, cmdType, cmdText, cmdParms); using (MySqlDataAdapter da = new MySqlDataAdapter(cmd)) { DataSet ds = new DataSet(); da.Fill(ds); cmd.Parameters.Clear(); return ds; } } } private static void PrepareCommand(MySqlConnection conn, MySqlTransaction trans, MySqlCommand cmd, CommandType cmdType, string cmdText, MySqlParameter[] cmdParms) { if (conn.State != ConnectionState.Open) conn.Open(); cmd.Connection = conn; cmd.CommandText = cmdText; if (trans != null) cmd.Transaction = trans; cmd.CommandType = cmdType; if (cmdParms != null) { foreach (MySqlParameter parm in cmdParms) cmd.Parameters.Add(parm); } }
- 临时兜底方案:如果短期无法调整代码,可以在应用启动时注册全局未处理异常捕获事件,过滤Finalize线程抛出的该特定 NullReferenceException,阻止进程直接崩溃,但该方案仅为临时规避,无法解决底层的资源泄漏、读取数据异常问题。
内容的提问来源于stack exchange,提问作者pioneer
相关产品推荐
相关产品推荐

