服务器上部署的Mysql,服务器上可登录成功,远程电脑无法连接的

一、无法连接远程服务器上的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防火墙图形界面:

  1. 控制面板 -> Windows Defender 防火墙

  2. 高级设置 -> 入站规则

  3. 新建规则 -> 端口 -> 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. 如果使用云服务器

如果你使用的是云服务器(如阿里云、腾讯云等):

  1. 检查安全组规则,确保3306端口已开放

  2. 检查实例的网络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

  1. 查找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 并成功登录后:

  1. MySQL客户端缓存了某些认证信息

  2. 可能更新了客户端状态

  3. 后续的Java连接能够重用这些状态

但这不是根本解决方案,只是临时绕过问题。

总结:

根本原因是MySQL 8.0的认证机制与Java驱动不兼容。通过命令行登录后能正常工作是因为触发了某种状态缓存。

推荐解决方案:在数据库连接URL中添加 allowPublicKeyRetrieval=true 参数,这是最简单有效的解决方法。

四、SqlModel,only_full_group_by

代码是旧版本5.7版本的,服务器上的mysql是8.0引起的only_full_group_by问题

版本差异分析

本地 vs 生产环境差异

  1. 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
  1. 数据量差异的影响:

· 空表执行可能成功:某些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, ...

推荐做法

  1. 开发环境统一:确保开发、测试、生产环境的MySQL版本一致

  2. 代码规范:SQL语句遵循ANSI SQL标准,兼容所有MySQL版本

  3. 版本控制:在项目文档中明确支持的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

查看启动参数中的数据目录

  1. 迁移MySQL数据到E盘

步骤一:停止MySQL服务

bash 复制代码
net stop mysql80

# 或

sc stop mysql80

步骤二:备份和移动数据文件

  1. 备份当前数据

假设当前数据目录是

C:\ProgramData\MySQL\MySQL Server 8.0\Data

创建新目录

bash 复制代码
mkdir E:\MySQLData
  1. 复制数据文件

复制所有文件(包括隐藏文件)

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
  1. 验证迁移是否成功

-- 再次查看数据目录

bash 复制代码
SHOW VARIABLES LIKE 'datadir';

-- 测试数据库操作

SHOW DATABASES

  1. 清理旧数据(确认迁移成功后)

确认新位置运行正常后,可以删除旧数据

但建议保留备份一段时间

注意事项:

  1. 确保E盘有足够空间(至少是当前数据大小的2倍)

  2. 迁移前做好完整备份

  3. 如果有大量数据,迁移可能需要较长时间

  4. 检查MySQL错误日志(通常在数据目录或 C:\ProgramData\MySQL\MySQL Server 8.0\)

  5. 如果使用防火墙,确保新路径被允许访问

相关推荐
梁萌6 小时前
MySQL数据库分库分表介绍
数据库·mysql·shardingsphere·分库分表
Cat God 0078 小时前
SQL使用及注意事项
数据库·sql·mysql
华仔啊9 小时前
如何避免MySQL死锁?资深DBA的9条黄金法则
后端·mysql
@老蝴9 小时前
MySQL数据库 - 约束和联合查询
android·数据库·mysql
程序猿20239 小时前
MySQL索引使用--最左前缀法则
数据库·mysql
她说..12 小时前
MySQL数据处理(增删改)
java·开发语言·数据库·mysql·java-ee
Alex Gram12 小时前
MySQL实时同步到SQL Server:技术方案与实现路径
数据库·mysql
计算机学姐15 小时前
基于SSM的网上花店销售系统【2026最新】
java·vue.js·mysql·java-ee·tomcat·intellij-idea·mybatis
嫂子的姐夫15 小时前
py连接mysql
数据库·爬虫·mysql
晨曦54321016 小时前
数据库视图:数据安全与查询利器
数据库·sql·mysql