C#调用mysqldump提示命令不识别 修改后程序长时间卡死如何解决
问题原因分析
初始报错找不到mysqldump的原因
你最开始的cd命令没有加/D参数,cd默认只能切换同盘符下的目录,如果你的C#程序运行时的工作目录不在C盘,就无法成功切换到MySQL的bin目录,导致系统找不到mysqldump.exe程序。
加/D后卡死的原因
你开启了--verbose=true参数,mysqldump会持续输出调试日志到标准输出流和标准错误流,而你没有对Process的输出流做任何读取处理,当流的缓冲区被占满后,mysqldump进程会被阻塞等待缓冲区释放,就会出现无限卡死的情况,属于典型的进程流死锁问题。
解决方案
推荐直接调用mysqldump.exe而非嵌套cmd.exe,可控性更高,也能避免路径切换的问题,参考实现代码如下:
// 明确指定mysqldump的完整路径,避免切换目录 string mysqldumpPath = @"C:\Program Files\mysql\mysql server 5.6\bin\mysqldump.exe"; // 输出路径用绝对路径,确保有写入权限,比如放在D盘或者程序运行目录 string outputPath = @"D:\mydb.sql"; ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = mysqldumpPath, // 去掉--verbose参数,不需要调试日志的话可以大幅减少输出 Arguments = "--user=user --password=pwd --host=localhost --protocol=tcp --port=3306 --default-character-set=utf8 --skip-triggers \"db\"", CreateNoWindow = true, // 重定向标准输出和错误流,避免缓冲区满阻塞 RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; using (Process process = Process.Start(startInfo)) { // 异步读取错误流,避免阻塞 string error = process.StandardError.ReadToEnd(); // 直接将标准输出写入到sql文件,替代cmd的重定向符号 using (var fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) { process.StandardOutput.BaseStream.CopyTo(fs); } // 可以加超时逻辑,避免无限等待,示例为最多等待10分钟 if (!process.WaitForExit(1000 * 60 * 10)) { process.Kill(); throw new TimeoutException("数据库导出超时"); } // 检查进程退出码,正常执行成功返回0,非0则为执行出错 if (process.ExitCode != 0) { throw new Exception($"导出失败,错误信息:{error}"); } }
注意事项
- 输出路径不要选择系统权限限制的目录(比如C盘根目录、Program Files目录),建议指定到程序运行目录、用户目录等普通权限可写入的位置
- 生产环境不要硬编码数据库账号密码,建议通过配置文件加密存储
- 如果确实需要保留调试日志,可以异步读取标准输出内容存储到日志文件,不要开启verbose后不处理输出流
内容的提问来源于stack exchange,提问作者Sweet MBH
相关产品推荐
相关产品推荐

