做.NET开发的朋友十有八九都遇到过这毛病:项目跑得好好的,换到另一台机器、升级了个环境,SqlSugar连MySql 8.0.29突然开始报错。更气人的是报错信息千奇百怪,有说“Authentication method not supported”的,有说“Unable to connect to any of the specified MySQL hosts”的,还有直接在连接字符串上甩脸色的。
这篇文章我就围绕“SqlSugar 连接MySql 8.0.29报错”这件事,把常见报错长相、根因、排查思路和最终能落地的连接配置全部捋一遍。适合用SqlSugar对接MySQL的初学者,也适合被这类问题卡过半天、想一次性把坑填平的同学。我会把版本选型、驱动差异、连接串参数、完整实操流程都展开讲,最后附一张常见问题速查表,方便你直接对着报错抄答案。
1. 先搞清楚报错到底在报什么
1.1 最常见的几种报错长相
不同时间、不同环境遇到的报错可能长得完全不一样,但背后往往指向同一批原因。我把平时遇到最多的几种贴出来,你先对号入座。
第一种,登录认证相关。报错一般长这样:
MySqlException: Authentication to host 'localhost' for user 'root' using method 'caching_sha2_password' failed with message: Reading from the stream has failed.或者:
MySqlException: Authentication method 'caching_sha2_password' not supported by any of the available plugins.第二种,网络层面的连接失败:
MySqlException: Unable to connect to any of the specified MySQL hosts.第三种,连接字符串参数不被识别:
ArgumentException: The given key 'SslMode' was not present in the dictionary.第四种,权限问题:
MySqlException: Access denied for user 'root'@'localhost' (using password: YES)第五种,不太起眼但特别坑的——表建不出来或字段类型怪异。SqlSugar的CodeFirst在MySQL 8上偶发建表后主键丢失,或者TINYINT(1)被当成bool导致查出来的值不对,这类问题也经常被误报成“连接不上”。
1.2 分门别类缩小排查范围
拿到报错不要慌,先把错误分成三类:认证类、网络类、参数类。认证类基本是MySQL 8的身份认证插件与驱动版本不匹配,网络类是服务端或防火墙问题,参数类是连接字符串写法问题。
我的建议是不要直接百度报错原文,先按下面这个顺序自查:
- 确认MySQL服务真的活着,端口能通。
- 确认账号密码和host授权没问题。
- 确认驱动包版本和SqlSugar版本都在合理范围内。
- 确认连接字符串里SSL参数、公钥参数和字符集参数没有踩雷。
- 最后再怀疑代码层面的写法。
这套顺序看起来简单,但能解决八成的问题。接下来我按这个链路,把每一步的原理和操作细节都拆给你看。
2. 版本和驱动:SqlSugar与MySql 8.0.29的兼容性真相
2.1 MySql 8.0认证方式变化带来的连锁反应
MySQL 8.0默认的身份认证插件从老版本的mysql_native_password换成了caching_sha2_password。这个改动本意是提升安全性,但副作用就是:太老的数据库驱动根本不认识新插件。
caching_sha2_password在第一次认证时需要做额外的密钥交换,如果客户端驱动版本太老,或者连接字符串里没有允许获取公钥,就会在握手阶段直接失败。很多用MySql.Data 6.x、8.0.11之前版本的朋友,连MySQL 8.0.29时遇到“Authentication method 'caching_sha2_password' not supported”,根因就是这里。
解决办法有两个方向。一个是升级驱动,让驱动支持新插件;另一个是把MySQL账号改回老认证插件。升级驱动是正路,改账号插件属于临时方案,能不动数据库配置尽量别动。
2.2 SqlSugar版本怎么选
SqlSugar本身分两大系列:.NET Framework用的SqlSugar,和.NET Core / .NET 5+用的SqlSugarCore。不管哪个系列,连接MySQL 8建议使用较新稳定版。
以SqlSugarCore为例,5.1.4.x以上版本对MySQL 8的支持已经比较完善,连接串写法也更规范。如果你还在用4.x甚至更早的版本,遇到MySQL 8的上报错概率会明显变大。4.x不是不能用,但它的连接字符串解析、驱动适配都相对老旧,遇到8.0.29这种新版本数据库时,容易在不起眼的地方出问题。
如果条件允许,我建议直接升级到5.1.4.x之后的最新稳定版,然后配套使用MySql.Data8.0.29以上或MySqlConnector2.2.x以上驱动。这套组合我实测下来最稳。
2.3 驱动二选一:MySql.Data还是MySqlConnector
这是很多人忽略的点。SqlSugar支持两类MySQL驱动:
MySql.Data:Oracle官方的MySQL .NET驱动,历史最久,资料最多。MySqlConnector:社区维护的高性能驱动,对Async支持更好,连接串参数略有些不同。
选哪个?我的看法是:没有历史包袱就选MySqlConnector,它在连接池管理、SSL处理、异步性能上都更现代。如果项目里早就用了MySql.Data,那也别急着换,把版本升到8.0.29以上即可。
但要注意一个细节:SqlSugar5.x里的DbType.MySql默认走MySql.Data,而DbType.MySqlConnector才走MySqlConnector。如果选错了驱动类型,即使连接字符串写得再对,也会出现驱动加载不上的诡异问题。
3. 连接字符串:90%问题的藏身处
3.1 一份完整可用的连接字符串长什么样
连接字符串是SqlSugar连接MySQL时最核心的一环。很多报错看起来莫名其妙,实际上就是连接字符串里某个参数写错、写漏或写多余了。
这里放一份我常用的、经过MySQL 8.0.29验证过的连接字符串:
Server=localhost;Port=3306;Database=testdb;Uid=root;Pwd=yourpassword;SslMode=None;AllowPublicKeyRetrieval=true;CharSet=utf8mb4;ConnectionTimeout=30;对应SqlSugar里的写法:
public class DbContext { public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig() { ConnectionString = "Server=localhost;Port=3306;Database=testdb;Uid=root;Pwd=yourpassword;SslMode=None;AllowPublicKeyRetrieval=true;CharSet=utf8mb4;ConnectionTimeout=30;", DbType = DbType.MySql, IsAutoCloseConnection = true, InitKeyType = InitKeyType.Attribute }); }注意:
DbType.MySql对应MySql.Data驱动。如果你NuGet装的是MySqlConnector,这里要改成DbType.MySqlConnector,两者不能混用。
3.2 参数逐个讲透:SslMode、AllowPublicKeyRetrieval、CharSet、TinyAsBoolean
很多人看着连接字符串里一堆参数,不知道哪些该删、哪些该留。我挑几个关键参数展开说。
SslMode
MySQL 8默认开启了SSL支持,但很多时候本地开发环境根本没配SSL证书。如果你不告诉驱动“不要用SSL”,它默认就会尝试SSL握手,一旦握手失败,报错就是“Reading from the stream has failed”或者“SSL Connection Error”。
本地开发或内网环境,直接写SslMode=None最省事。如果公司强制要求加密连接,那就要配置证书,并把SslMode改为Required或VerifyCA,同时把证书路径写进连接串。
AllowPublicKeyRetrieval
这个参数名字很长,但作用很直接:当使用caching_sha2_password认证且没有SSL时,是否允许客户端从服务器获取RSA公钥来完成密码加密传输。
如果不设这个参数,连接时会直接抛异常,提示:
MySqlException: Reading from the stream has failed.在你的开发环境里加上AllowPublicKeyRetrieval=true,这个坑就填平了。考虑到安全性,生产环境如果开了SSL,其实可以把它设成false,但内网开发环境就别纠结了,true就对了。
CharSet
MySql 8默认字符集是utf8mb4。如果你的连接字符串没有显式指定字符集,某些驱动会默认用utf8或latin1,于是中文写入查询就会出现乱码。连接字符串里写CharSet=utf8mb4能从根本上避免这个问题。
TinyAsBoolean
这个参数不是连接字符串标配,但如果你的表里有TINYINT(1)字段,某些驱动会默认把它映射成bool,导致查询结果类型对不上。遇到这种问题,可以试试在连接字符串里加:
TinyAsBoolean=false;不过要注意,TinyAsBoolean不是所有驱动都识别,MySql.Data较新版本支持,MySqlConnector对这类细粒度参数的处理方式略有不同。用之前先确认自己的驱动版本。
3.3 针对不同环境我给的三套配置模板
光说理论不够,我直接把三种常见环境的连接字符串模板放出来,复制改密码就能用。
开发环境(本地直连,不开SSL):
Server=127.0.0.1;Port=3306;Database=testdb;Uid=root;Pwd=123456;SslMode=None;AllowPublicKeyRetrieval=true;CharSet=utf8mb4;ConnectionTimeout=30;测试环境(内网服务器,MySQL启用了SSL但证书不做强校验):
Server=192.168.1.100;Port=3306;Database=testdb;Uid=appuser;Pwd=apppass;SslMode=Preferred;CharSet=utf8mb4;ConnectionTimeout=30;生产环境(要求强制SSL加密,校验CA证书):
Server=db.prod.example.com;Port=3306;Database=testdb;Uid=appuser;Pwd=apppass;SslMode=VerifyCA;CertificateFile=/path/to/ca.pem;CharSet=utf8mb4;ConnectionTimeout=30;生产环境如果真的开启了SSL,
AllowPublicKeyRetrieval就可以不写了。因为SSL已经把传输链路加密,RSA公钥获取就不是必需的了。
4. 一步步实操:从零到连上数据库
4.1 环境检查:确认数据库和端口都活着
很多连接报错其实不是SqlSugar的问题,是网络根本没通。所以我习惯性先做两步检查。
第一步,确认MySQL服务在跑。Windows下看服务管理器里MySQL进程状态,Linux下执行:
systemctl status mysqld或者用mysqladmin ping:
mysqladmin -uroot -p ping第二步,确认端口通不通。在应用服务器上执行:
telnet 127.0.0.1 3306如果telnet显示无法连接,说明3306端口根本没监听,或者被防火墙拦了。这里我踩过不少坑:很多云服务器默认安全组没放行3306,本地连不上,还以为是SqlSugar和MySQL版本冲突。
Windows下也可以用PowerShell快速测端口:
Test-NetConnection -ComputerName localhost -Port 3306输出的TcpTestSucceeded如果是True,说明端口通。
4.2 NuGet包安装与SqlSugar实例化
环境通了之后,接下来就是装包、写代码。
用Visual Studio或者命令行安装这两个包之一:
Install-Package SqlSugarCore Install-Package MySql.Data -Version 8.0.29或者:
Install-Package SqlSugarCore Install-Package MySqlConnector装好之后,实例化SqlSugarScope:
using SqlSugar; var db = new SqlSugarScope(new ConnectionConfig() { ConnectionString = "Server=localhost;Port=3306;Database=testdb;Uid=root;Pwd=yourpassword;SslMode=None;AllowPublicKeyRetrieval=true;CharSet=utf8mb4;", DbType = DbType.MySql, IsAutoCloseConnection = true, InitKeyType = InitKeyType.Attribute, MoreSettings = new ConnMoreSettings() { IsAutoRemoveDataCache = true } });如果用的是MySqlConnector,就把DbType.MySql改成DbType.MySqlConnector。这一步很多人容易忽略,连不上时先检查一下DbType和驱动是否匹配。
4.3 CodeFirst初始化与建库
连接串配好之后,推荐先跑一个最简单的连通性测试,而不是直接写业务代码。比如先执行:
db.Ado.CheckConnection();返回true就说明连接没问题。如果返回false,说明连接环节依然有拦路虎,按前文顺序排查。
如果你要用SqlSugar的CodeFirst自动建表,还需要注意建库的问题。SqlSugar在数据库不存在时,可以先创建数据库,再创建表:
// 先建库 db.DbMaintenance.CreateDatabase(); // 再建表 db.CodeFirst.InitTables(typeof(User), typeof(Order));实体类示例:
[SugarTable("user")] public class User { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } [SugarColumn(ColumnDataType = "varchar(50)", IsNullable = false)] public string Name { get; set; } [SugarColumn(ColumnDataType = "datetime", IsNullable = true)] public DateTime? CreateTime { get; set; } }这里有个MySQL 8特有的小坑:Linux下MySQL默认表名区分大小写,Windows下不区分。如果你的实体名和表名大小写不一致,SqlSugar生成的SQL可能找不到表。解决方案是实体上显式用[SugarTable("user")]指定表名,并保持和数据库里的表名完全一致。
4.4 跑通第一条查询
连接确认没问题后,直接写一条最简单的查询验证全链路:
var user = db.Queryable<User>().Where(u => u.Id == 1).First(); Console.WriteLine(user?.Name);如果能正常输出用户名,说明SqlSugar到MySql 8.0.29这条路已经通了。之后再逐步加业务逻辑,遇到问题也更容易定位。
5. 常见报错速查表与排查技巧
5.1 报错对应表
我在实际项目中把这些报错和对应的解决方案整理成了下面这张表,你在遇到问题的时候可以直接对照。
| 报错信息 | 可能原因 | 解决方向 |
|---|---|---|
| Authentication method 'caching_sha2_password' not supported | 驱动版本过旧 | 升级MySql.Data到8.0.29+,或换MySqlConnector |
| Reading from the stream has failed | SSL握手失败或公钥获取被禁止 | 连接串加SslMode=None、AllowPublicKeyRetrieval=true |
| Unable to connect to any of the specified MySQL hosts | 网络不通、端口未开、服务未启动 | 检查服务状态、防火墙、安全组,用telnet测3306 |
| Access denied for user 'root'@'localhost' | 密码错误或host授权不足 | 确认账号密码,或给用户加%访问权限 |
| The given key 'SslMode' was not present in the dictionary | 驱动不认识SslMode参数 | 换新版驱动,或改用UseSslMode写法 |
| The requested database 'testdb' does not exist | 数据库名写错或数据库未创建 | 先用客户端工具建库,或用CreateDatabase()建库 |
| 中文乱码 | 字符集未指定 | 连接串加CharSet=utf8mb4,同时确认表字符集 |
这张表不是万能的,但覆盖了我遇到过的八成场景。剩下两成是项目里特殊配置导致的,得靠日志进一步定位。
5.2 三个我踩过坑的隐性细节
排查到后面你会发现,有些报错不是一上来就能看透的。这里有三个隐性细节,分享出来希望能帮你少走弯路。
第一个是连接池里的旧连接。SqlSugar默认会做连接复用,如果你改了数据库密码或账号权限,但连接池里还留着旧连接,可能继续用旧凭据去连,导致间歇性报Access denied。这时候最简单粗暴的办法是重启应用,或者重启IIS/进程,把连接池清掉。
第二个是数据库名称的引号问题。MySQL 8里数据库名、表名可能带反引号,SqlSugar通常能自动处理,但如果你的实体名刚好是关键字(比如Order、Group),就容易被解析错。稳妥做法是实体上用[SugarTable("order")]显式转义。
第三个是MySQL账号的host匹配顺序。MySQL授权表里可能有root@localhost和root@%两条记录,应用通过127.0.0.1连接时,有时匹配到的是root@localhost,密码不同就会Access denied。别只盯着密码,用下面的SQL看下用户权限:
SELECT user, host, plugin FROM mysql.user;如果plugin列显示caching_sha2_password,但驱动太老,也会报前文的认证错误。这个检查能快速定位认证和授权两方面的问题。
5.3 你以为的数据库报错其实并不在数据库层
还有一种情况,项目里报错看着像数据库连接问题,但实际是前端或网关层拦截了请求。比如浏览器打开页面时提示“此连接已被阻止”之类的安全拦截信息,这通常是浏览器安全策略、HTTPS证书校验或代理设置导致的,跟后端SqlSugar连MySQL完全是两码事。
遇到这类情况,我的建议是先看后端日志,确认SqlSugar有没有真的抛出MySqlException。如果后端日志显示连接正常,只有浏览器端报拦截,那排查方向就要切到请求链路的中间层,别在连接字符串上死磕。判断“是不是数据库层问题”最简单的方法就是单独跑一个控制台程序,用同一套连接串直连数据库,能通就说明SqlSugar和MySQL没问题。
这个习惯很重要。很多时候项目里层层包裹,数据库报错被上层拦截或包装,真正的异常信息被吞掉了。我一般会在排查初期先用db.Ado.CheckConnection()跑一下,把数据库层的问题独立验证掉,再做其他排查。
6. 写在最后的一点个人体会
SqlSugar连接MySql 8.0.29报错,绝大多数情况不是SqlSugar本身的问题,而是版本、驱动、连接串三者配合不当。我踩过几次坑之后,总结的排查顺序非常固定:先看驱动版本和SqlSugar版本是否兼容,再查连接串里SSL、公钥、字符集这三个高频坑,然后确认账号权限和网络端口,最后才去怀疑代码写法。
如果你的项目刚起步,我建议直接使用SqlSugarCore最新稳定版 +MySqlConnector,连接串按SslMode=None;AllowPublicKeyRetrieval=true;CharSet=utf8mb4这套打底,能省掉后面一大半的破事。别一上来就追求生产级SSL配置,先把链路跑通再逐步收紧安全策略,这才是务实的路线。
最后再分享一个调试小技巧:连接串里临时加上Logging=true,能把驱动内部执行的关键日志打到控制台,很多模糊报错会瞬间变得清晰。这个参数生产环境别开,但排查问题的时候是真的好用。