You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#调用MySQL存储过程报SocketException连接超时问题排查

问题根因
  • 你碰到的10060错误本质是命令执行超时,不是数据库连接失败。MySql.Data驱动默认的命令执行超时是30秒,你的存储过程实际执行时间超过这个阈值后,驱动会主动断开TCP连接,最终抛出Socket响应超时的错误。你直接在数据库客户端执行存储过程能成功,是因为多数数据库GUI客户端默认不会设置这么短的执行超时限制。
  • 存储过程存在严重的逻辑冗余:你写的WHILE循环会按照cpe表的总行数重复执行N次,但循环体内的INSERT语句是完全相同的全表分组查询逻辑,没有用到循环变量i做任何分批过滤,等于把同一个全表扫描+分组+插入的操作重复跑N遍。只要cpe表数据量超过几千行,执行时间会线性暴涨,必然触发超时。
  • C#代码存在隐性问题:你声明了值为null的MySqlTransaction对象,还把这个null赋值给了cmd.Transaction属性,虽然当前场景没触发异常,但后续开启事务时极易引发空引用错误。
修复方案

1. 先优化存储过程,删除无意义的循环

你的需求本质是把cpe表按cveMatch分组统计后插入cve表,单条INSERT...SELECT语句就能完成,完全不需要套循环,优化后存储过程执行效率会提升N个数量级:

DROP PROCEDURE IF EXISTS cveTableFill;
DELIMITER ;;
CREATE PROCEDURE cveTableFill()
BEGIN
  INSERT IGNORE INTO cve(cve_name, cpeMatchCount) 
  SELECT c.cveMatch, COUNT(c.cveMatch) 
  FROM cpe c 
  GROUP BY c.cveMatch 
  HAVING COUNT(c.cveMatch) > 0;
END;;
DELIMITER ;

如果确实因为数据量过大需要分批插入,也要在循环内加主键/时间范围过滤条件,每次只处理一批数据,不要每次循环都扫描全表。

2. 修复C#代码问题,调整超时配置

  • 删除无效的null事务赋值,需要用事务时显式从连接对象创建,执行完成后提交
  • 给SqlCommand设置合理的超时时间,适配长耗时操作场景
  • 异常打印时输出完整堆栈,不要只打Message字段,方便定位问题
    修复后的代码如下:

业务方法代码

public void BasicCveInfoFill()
{
    try
    {
        using(MySqlConnection conn = GetConnection())
        {
            conn.Open();
            // 不需要事务可以删掉下面这行using块
            using(MySqlTransaction transaction = conn.BeginTransaction())
            {
                using(MySqlCommand cmd = new MySqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.Transaction = transaction;                     
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "cveTableFill";
                    // 命令超时时间单位为秒,根据实际数据量调整,这里示例设为5分钟
                    cmd.CommandTimeout = 300;
                    var affectedRows = cmd.ExecuteNonQuery();
                    // 开启事务必须调用Commit,否则操作会回滚
                    transaction.Commit();
                }
            }
        }
    }
    catch(Exception ex)
    {
        // 打印完整异常信息,不要只打ex.Message
        Console.WriteLine(ex.ToString());
    }
}

数据库连接方法代码

public MySqlConnection GetConnection()
{
    // 也可以在连接字符串中配置全局默认命令超时,单位同样是秒
    string connString = @"server=localhost;user=root;database=test;password=;Default Command Timeout=300";
    return new MySqlConnection(connString);
}

3. 存储过程执行状态判断方法

  • 正常情况下ExecuteNonQuery()方法会阻塞等待存储过程执行完成,方法正常返回、拿到受影响行数就代表存储过程执行成功;方法抛出异常即代表执行过程中出现错误,不需要额外做状态轮询。
  • 如果需要排查长耗时存储过程的执行进度,可以在MySQL中执行show processlist命令,查看对应会话的执行状态、已运行时间、当前执行的SQL片段,判断任务是否正常运行。
  • 不建议将命令超时设置为无限大,如果优化SQL后单次操作仍需要超过10分钟执行时间,优先考虑改成分批处理逻辑,避免长时间占用数据库连接引发其他问题。

内容的提问来源于stack exchange,提问作者DuckDuckGoose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 01:15:37