.NET Standard 2.1下使用MySql.Data时如何识别MySqlException中的瞬态错误?
我正好遇到过类似的问题,在使用MySql.Data和.NET Standard 2.1开发时,确实没有内置的IsTransient属性来快速判断临时异常。不过我们可以通过自定义扩展方法结合MySQL的瞬态错误代码来解决这个问题,下面是具体的实现方案和相关细节:
解决方法:自定义瞬态异常判断逻辑
我们可以给MySqlException写一个扩展方法,通过匹配错误代码来判断是否为临时异常。这种方式灵活且完全可控,适配.NET Standard 2.1的环境。
扩展方法实现
using MySql.Data.MySqlClient; using System.Collections.Generic; public static class MySqlExceptionExtensions { // 预定义MySQL常见的瞬态错误代码集合 private static readonly HashSet<int> TransientErrorCodes = new HashSet<int> { 1040, // 连接数过多(Too many connections) 1042, // 无法解析主机地址(Can't get hostname for your address) 2002, // 无法通过Socket连接本地MySQL服务 2003, // 无法连接到指定主机的MySQL服务 2006, // MySQL服务器已断开连接(MySQL server has gone away) 2013, // 查询过程中丢失与服务器的连接 2026, // SSL连接错误 1205, // 锁等待超时(Lock wait timeout exceeded) 1213, // 检测到死锁(Deadlock found when trying to get lock) 1203, // 用户连接数超过限制 1153, // 数据包大小超过max_allowed_packet限制(临时调整配置或重试可能解决) 1154, // 读取通信数据包时出错 1156, // 写入通信数据包时出错 }; /// <summary> /// 判断MySQL异常是否为临时可重试的异常 /// </summary> public static bool IsTransient(this MySqlException ex) { return TransientErrorCodes.Contains(ex.Number); } }
使用示例
在捕获异常时直接调用扩展方法即可:
try { // 执行你的数据库操作逻辑 using var conn = new MySqlConnection("你的连接字符串"); conn.Open(); // ... } catch (MySqlException ex) { if (ex.IsTransient()) { // 处理临时异常:比如执行重试逻辑、记录告警等 Console.WriteLine($"检测到临时MySQL异常(错误码:{ex.Number}),准备重试..."); } else { // 非临时异常,直接抛出或进行针对性处理 throw; } }
常见MySQL瞬态错误代码说明
上面集合中的错误码对应以下典型的临时场景:
1040/1203: 服务器连接数耗尽,等待其他连接释放后重试即可2002/2003/2013: 网络波动、服务器临时重启或未启动,恢复后可正常连接2006: 长时间无操作导致连接被服务器回收,重新建立连接即可1205/1213: 事务锁冲突或死锁,重试事务大概率可以成功1153/1154/1156: 网络数据包传输异常,重试操作可能恢复
额外注意事项
- 不同MySQL版本的错误码可能略有差异,建议结合你使用的MySQL版本官方文档核对补充
- 实现重试逻辑时,建议使用指数退避策略(比如第一次等2秒,第二次等4秒,以此类推),避免短时间内频繁重试给服务器带来额外压力
- 如果使用Polly等重试库,可以直接结合这个扩展方法配置重试规则,示例:
var retryPolicy = Policy .Handle<MySqlException>(ex => ex.IsTransient()) .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); retryPolicy.Execute(() => { // 你的数据库操作代码 });
内容的提问来源于stack exchange,提问作者Christian Cascone
相关产品推荐
相关产品推荐

