一、无法连接远程服务器上的Mysql的问题场景
windowns服务器部署了一台mysql,在服务器上用mysql -uroot -p 输入密码可登录成功,但在自己的电脑上用navicat连不上,报2003 - Can't connect to MySQL server on '12.68.*.*' (10060 "Unknown error")
这个错误表示无法连接到MySQL服务器。以下是解决这个问题的步骤:
1. 检查网络连通性
在你的电脑上测试是否能访问服务器
ping 服务器IP
测试MySQL端口(3306)是否可访问
telnet 服务器IP 3306
或者使用
nc -zv 服务器IP 3306
2. 检查MySQL绑定地址配置
在Windows服务器上:
步骤1:找到MySQL配置文件
· 通常位于:
bash
C:\ProgramData\MySQL\MySQL Server X.X\my.ini
或:C:\Program Files\MySQL\MySQL Server X.X\my.ini
步骤2:修改配配置
找到 [mysqld] 部分
mysqld
修改或添加以下行:
bind-address = 0.0.0.0 # 允许所有IP连接
或bind-address = 服务器ip # 绑定到特定IP
步骤3:重启MySQL服务
#以管理员身份运行PowerShell或CMD
bash
net stop mysql
net start mysql
或使用服务名可能为 MySQL80、MySQL57 等
3. 检查Windows防火墙设置
步骤1:允许MySQL端口通过防火墙
允许3306端口入站
bash
New-NetFirewallRule -DisplayName "MySQL Port" -Direction Inbound -Protocol TCP -LocalPort 3306 -Action Allow
或者通过Windows防火墙图形界面:
-
控制面板 -> Windows Defender 防火墙
-
高级设置 -> 入站规则
-
新建规则 -> 端口 -> TCP 3306 -> 允许连接
步骤2:检查是否还有其他防火墙
· 服务器上是否有第三方安全软件(如360、火绒等)
· 网络设备防火墙(路由器、交换机等)
4. 检查MySQL用户权限
在服务器上登录MySQL,然后执行:
bash
mysql -u root -p
回车输入密码
-- 查看当前用户权限
bash
SELECT host, user FROM mysql.user;
-- 授权root用户从任意IP访问(生产环境慎用)
bash
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '你的密码' WITH GRANT OPTION;
-- 或者授权从特定IP访问
bash
GRANT ALL PRIVILEGES ON *.* TO 'root'@'106.23.%' IDENTIFIED BY '你的密码';
-- 刷新权限
bash
FLUSH PRIVILEGES;
5. 检查MySQL是否在运行
查看MySQL服务状态
bash
sc query mysql
# 或
Get-Service mysql
6. 检查端口监听情况
在服务器上执行:
查看3306端口监听情况
bash
netstat -an | findstr :3306
# 应该显示类似:
# TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING
# 或
# TCP 10.80.2.15:3306 0.0.0.0:0 LISTENING
7. 检查MySQL错误日志
查看MySQL错误日志,通常位于:
· C:\ProgramData\MySQL\MySQL Server X.X\Data\主机名.err
· 或MySQL安装目录下的data文件夹
8. 连接时指定端口
在Navicat连接时,确保:
· 主机:服务器ip
· 端口:3306(默认)
· 用户名:root
· 密码:你的密码
9. 如果使用云服务器
如果你使用的是云服务器(如阿里云、腾讯云等):
-
检查安全组规则,确保3306端口已开放
-
检查实例的网络ACL配置
快速检查清单:
✅ 服务器本地能连接MySQL吗?
✅防火墙是否开放了3306端口?
✅MySQL配置中bind-address是否正确?
✅MySQL用户是否有远程连接权限?
✅网络是否互通?
按照以上步骤逐一排查,通常能解决连接问题。建议按顺序检查,从最简单的网络连通性开始。
以上是排查问题的场景,我先是防火墙允许3306,然后还是远程连接不上,就去ping mysql所在的服务器ip,ping不通,服务器是在海外,还好运维的同事能ping通,但还是Navicat登录不上,
对标上述排查场景第4步,才知道,mysql针对不同的用户,允许不同的host访问,单独添加了我本地电脑的ip以及账户和运维的ip,依然无法登录连接,最后按第4步
先是查
bash
SELECT host, user FROM mysql.user;
+-----------+------------------+
| host | user |
+-----------+------------------+
| localhost | mysql.infoschema |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
+-----------+------------------+
发现没有允许外部访问的ip和账号,于是
试了ip为 %:
bash
:GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' IDENTIFIED BY '你的密码' WITH GRANT OPTION;
此时运维可以远程连接成功mysql,我还是无法成功,运维用的是网线,我用的是wifi,换成网线,我也可以登录连接成功Mysql,推论是wifi和能连接上海外服务器不在一个网段上。
因为服务器的java程序是和mysql在同一台机器,java程序的jdbc的url是localhost:3306,因为mysql安装时默认的root用户,允许的host就是localhost,没有其他ip,不过可以在安装时指定,如果对mysql不熟悉,也可以按上面的第4步添加更改用户和host,自然java程序的账号就是root,密码是安装时的设置的密码。
如果java程序和mysql不在同一台机器,自然就不能按上述配置 jdbc 了,url就是mysql所在的ip:3306
账号是前面第4步或者安装时新添加的用户,如前面所讲,host配置的是"%"号,任何这个用户,只要密码对,就能访问数据库。
二、查找my.ini
- 查找MySQL配置文件位置
不同的版本,my.ini所在的位置不一样,一版位置如下,
bash
1.1· C:\ProgramData\MySQL\MySQL Server 8.0\my.ini
1.2· C:\ProgramData\MySQL\MySQL Server 5.7\my.ini
1.3 MySQL安装目录下:C:\Program Files\MySQL\MySQL Server X.X\my.ini
注意:mysql8.0以上的版本,ProgramData 文件夹默认是隐藏的,需要先在文件夹选项中取消隐藏。8.0以上的一般在1.1
三、Public Key Retrieval is not allowed错误
Mysql服务器上输入密码登录成功后,java程序启动时连接Mysql才能成功,才能启动成功。才不会报这个错。
Java应用程序无法连接到MySQL数据库,报 "Public Key Retrieval is not allowed" 错误。这是一个MySQL 8.0常见的认证问题。
核心错误:
java
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:
Public Key Retrieval is not allowed
原因:
· MySQL 8.0默认使用了caching_sha2_password身份验证插件
· Java程序(特别是旧版本驱动)连接时需要获取公钥,但默认不允许
· 当你先通过命令行登录MySQL后,某些客户端缓存或状态被更新,使得后续连接可以工作
解决方案:
方案1:修改数据库连接URL(推荐)
在Java配置文件中,修改数据库连接URL,添加 allowPublicKeyRetrieval=true 参数:
java
原始URL(有问题):
jdbc:mysql://localhost:3306/scm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&autoReconnect=true&failOverReadOnly=false&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
修改后URL(添加allowPublicKeyRetrieval=true):
jdbc:mysql://localhost:3306/scm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&autoReconnect=true&failOverReadOnly=false&allowPublicKeyRetrieval=true&sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
方案2:更换MySQL驱动版本
如果你使用的是旧版MySQL驱动(如5.x),建议升级到支持MySQL 8.0的驱动:
XML
<!-- Maven依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version> <!-- 使用8.x版本 -->
</dependency>
方案3:修改MySQL用户认证方式
在MySQL中修改用户密码认证方式为旧版
bash
-- 连接到MySQL
mysql -u root -p
-- 修改root用户的认证方式(将'your_password'替换为实际密码)
ALTER USER 'admin'@'ip' IDENTIFIED WITH mysql_native_password BY 'your_password';
-- 或者针对特定用户(如果应用使用其他用户)
ALTER USER 'your_app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password';
-- 刷新权限
FLUSH PRIVILEGES;
为什么命令行登录后能正常工作?
当先执行 mysql -u root -p 并成功登录后:
-
MySQL客户端缓存了某些认证信息
-
可能更新了客户端状态
-
后续的Java连接能够重用这些状态
但这不是根本解决方案,只是临时绕过问题。
总结:
根本原因是MySQL 8.0的认证机制与Java驱动不兼容。通过命令行登录后能正常工作是因为触发了某种状态缓存。
推荐解决方案:在数据库连接URL中添加 allowPublicKeyRetrieval=true 参数,这是最简单有效的解决方法。
四、SqlModel,only_full_group_by
代码是旧版本5.7版本的,服务器上的mysql是8.0引起的only_full_group_by问题
版本差异分析
本地 vs 生产环境差异
- MySQL版本不同:
bash
· MySQL 5.6及以下:默认 sql_mode 不包含 only_full_group_by
· MySQL 5.7.5及以上:默认启用 only_full_group_by
· MySQL 8.0:强制启用 only_full_group_by
- 数据量差异的影响:
· 空表执行可能成功:某些MySQL版本对空表查询会放宽限制
· 有数据执行更严格:当表中有数据时,MySQL会进行更严格的语法检查
如何验证版本差异在出现问题的数据库上执行:
bash
-- 查看MySQL版本
SELECT VERSION();
-- 查看当前sql_mode
SELECT @@sql_mode;
在本地数据库执行相同的查询,对比结果。
根本原因:SQL模式差异
不同版本默认sql_mode对比
java
MySQL 5.6: 空或者较宽松
MySQL 5.7.5+: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE...
MySQL 8.0: 包含ONLY_FULL_GROUP_BY且无法完全移除
具体解决方案
方案1:修改sql_mode(推荐临时解决)
-- 查看当前sql_mode
bash
SELECT @@sql_mode;
-- 临时关闭only_full_group_by(当前会话有效)
bash
SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
-- 或者设置为兼容模式
bash
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
方案2:修改JFinal数据库连接配置
在数据库连接URL中添加参数
XML
jdbc.url=jdbc:mysql://localhost:3306/scm?
useUnicode=true&
characterEncoding=utf8&
zeroDateTimeBehavior=convertToNull&
useSSL=false&
sessionVariables=sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
方案3:修复SQL语法(最彻底)
根据您的业务逻辑,
如果ebeln可能对应多行,需要所有字段分组
sql
SELECT
a.order,
SUM(netwr) AS TOTAL_AMOUNT,
a.LIFNR,
a.NAME1,
-- 列出所有需要的字段
...
FROM ...
WHERE ...
GROUP BY a.order, a.LIFNR, a.NAME1, a.factory, a.createDate, a.createName, ...
推荐做法
-
开发环境统一:确保开发、测试、生产环境的MySQL版本一致
-
代码规范:SQL语句遵循ANSI SQL标准,兼容所有MySQL版本
-
版本控制:在项目文档中明确支持的MySQL版本
方案 4:Java临时修改sql_mode
java
/ 在listOrderContract方法中,查询前临时修改sql_mode
public Page<Record> listOrderContract(...) {
// 临时关闭only_full_group_by
Db.update("SET SESSION sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''))");
try {
// 执行原有的paginate查询
return Db.paginate(...);
} finally {
// 恢复原设置(可选)
// Db.update("SET SESSION sql_mode = @@global.sql_mode");
}
}
这样既能快速解决问题,又不影响其他查询。长期来看,还是建议修复SQL语法以符合标准。
上述亲测都有效,具体用哪个,根据自己改动的便利及影响的大小权衡选择
五、MySql的data迁移
windowns服务器上装的mysql8.0以上的服务,没有给选择安装目录,data已经有数据,如何更改到E盘
在Windows服务器上,MySQL 8.0+的默认数据目录通常是:
1. 查看当前数据存储位置
方法一:通过MySQL命令查看
SHOW VARIABLES LIKE 'datadir';
方法二:查看MySQL配置文件
· 默认配置文件位置:
C:\ProgramData\MySQL\MySQL Server 8.0\my.ini
· 查看其中的 datadir 配置项
方法三:通过服务查看
打开PowerShell(管理员)
sc queryex mysql80
查看启动参数中的数据目录
- 迁移MySQL数据到E盘
步骤一:停止MySQL服务
bash
net stop mysql80
# 或
sc stop mysql80
步骤二:备份和移动数据文件
- 备份当前数据
假设当前数据目录是
C:\ProgramData\MySQL\MySQL Server 8.0\Data
创建新目录
bash
mkdir E:\MySQLData
- 复制数据文件
复制所有文件(包括隐藏文件)
bash
xcopy "C:\ProgramData\MySQL\MySQL Server 8.0\Data\*" "E:\MySQLData\" /E /H /C /I /Y
步骤三:修改MySQL配置文件
编辑 my.ini 文件(通常在 C:\ProgramData\MySQL\MySQL Server 8.0\ 或安装目录):
修改数据目录
datadir=E:/MySQLData
bash
修改二进制日志目录(如果需要)
log-bin=E:/MySQLData/mysql-bin
修改错误日志路径
log-error=E:/MySQLData/mysql-error.log
修改临时文件目录(可选)
tmpdir=E:/MySQLTemp
步骤五:设置目录权限
授予MySQL服务账户对E盘目录的完全控制权限
bash
icacls "E:\MySQLData" /grant "NT SERVICE\MySQL80":(OI)(CI)F /T
如果是Network Service账户
bash
icacls "E:\MySQLData" /grant "NT AUTHORITY\NETWORK SERVICE":(OI)(CI)F /T
步骤六:启动MySQL服务
bash
net start mysql80
- 验证迁移是否成功
-- 再次查看数据目录
bash
SHOW VARIABLES LIKE 'datadir';
-- 测试数据库操作
SHOW DATABASES
- 清理旧数据(确认迁移成功后)
确认新位置运行正常后,可以删除旧数据
但建议保留备份一段时间
注意事项:
-
确保E盘有足够空间(至少是当前数据大小的2倍)
-
迁移前做好完整备份
-
如果有大量数据,迁移可能需要较长时间
-
检查MySQL错误日志(通常在数据目录或 C:\ProgramData\MySQL\MySQL Server 8.0\)
-
如果使用防火墙,确保新路径被允许访问