当你的应用突然报出 java.sql.SQLException: Access denied for user 'api_user'@'localhost' 错误,就像数据库世界突然对你关上了大门。别担心,这不是世界末日,而是一场等待你破解的数据库连接谜题!

在这里插入图片描述

危机现场:当应用与数据库失联

2025-08-13 08:13:09.540 ERROR 17220 --- [nio-8080-exec-2] com.zaxxer.hikari.pool.HikariPool        
HikariPool-1 - Exception during pool initialization.
java.sql.SQLException: Access denied for user 'api_user'@'localhost' (using password: YES)

这段冰冷的错误日志背后,是一个身份验证危机:你的应用(api_user)正站在数据库(api_db)门前,手握钥匙(api_password),但门就是打不开!
在这里插入图片描述

破案第一步:重现犯罪现场

🔍 模拟应用登录行为

# 打开终端,模拟应用的登录行为
mysql -u api_user -p

当你按下回车后,会出现以下两种剧情:

  1. 悲剧结局:密码错误提示

    ERROR 1045 (28000): Access denied for user 'api_user'@'localhost' (using password: YES)
    
  2. 喜剧开端:成功登录提示

    Welcome to the MySQL monitor...
    mysql> 
    

不同剧情的解决之道

在这里插入图片描述

🚨 剧情一:用户根本不存在或密码错误

第1步:管理员身份入场
# 用root账号登录数据库
mysql -u root -p
# 输入你的数据库管理员密码
第2步:调查用户是否存在
-- 在MySQL中执行
SELECT user, host FROM mysql.user 
WHERE user = 'api_user';

查询结果解读:

  • 无结果 → 用户不存在
  • 有结果 → 用户存在但密码错误
第3步:重建用户(推荐方案,我的问题是权限问题)
-- 安全删除旧用户
DROP USER IF EXISTS 'api_user'@'localhost';

-- 创建新用户并设置密码
CREATE USER 'api_user'@'localhost' 
IDENTIFIED BY 'api_password'; -- 确保与配置文件一致

-- 授予数据库访问权限
GRANT ALL PRIVILEGES ON api_db.* 
TO 'api_user'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

在这里插入图片描述

第4步:检查权限是否生效
SHOW GRANTS FOR 'api_user'@'localhost';

预期结果:

GRANT USAGE ON *.* TO `api_user`@`localhost`
GRANT ALL PRIVILEGES ON `api_db`.* TO `api_user`@`localhost`

🎭 剧情二:用户能登录但应用仍报错

排查方向1:数据库是否存在
-- 在MySQL中执行
SHOW DATABASES;

关键检查点:

  • 列表中是否有 api_db
  • 数据库名称是否大小写敏感
  • 数据库字符集是否正确?

修复方案:

CREATE DATABASE IF NOT EXISTS api_db 
CHARACTER SET utf8mb4 
COLLATE utf8mb4_unicode_ci;
排查方向2:配置文件中的隐形杀手
# application.properties 检查点
spring.datasource.username=api_user
spring.datasource.password=api_password

常见陷阱:

  1. 密码前后有空格password= api_password
  2. 使用了中文标点password:api_password
  3. 特殊字符无需转义password=abc\!123 应改为 password=abc!123
排查方向3:权限缓存幽灵
# Linux系统
sudo systemctl restart mysql

# Windows系统
net stop mysql
net start mysql

缓存原理说明: MySQL有时会将权限信息缓存在内存中,即使你已经修改了权限。重启服务是清除缓存最有效的方式。

🛠️ 终极武器:连接测试代码

当所有方法都失效时,祭出这段"数据库连接测试器":

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConnectionTester {
    public static void main(String[] args) {
        // 配置信息 - 替换为你的实际参数
        String url = "jdbc:mysql://localhost:3306/api_db?"
                  + "useSSL=false&"
                  + "serverTimezone=Asia/Shanghai&"
                  + "allowPublicKeyRetrieval=true";
        
        String user = "api_user";
        String password = "api_password";
        
        System.out.println("🛠️ 正在测试数据库连接...");
        System.out.println("🔗 URL: " + url);
        System.out.println("👤 User: " + user);
        System.out.println("🔑 Password: " + password.replaceAll(".", "*"));
        
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            System.out.println("✅ 数据库连接成功!");
            System.out.println("ⓘ 数据库产品: " + conn.getMetaData().getDatabaseProductName());
            System.out.println("ⓘ 数据库版本: " + conn.getMetaData().getDatabaseProductVersion());
        } catch (Exception e) {
            System.err.println("❌ 连接失败:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

运行结果分析:

  • 连接成功:问题出在应用的其他部分(如HikariCP配置)
  • 相同错误:确认是数据库端权限问题(我出现的问题是权限问题,我给user重新赋予了权限)
  • 新错误提示:根据具体错误信息精准解决

在这里插入图片描述

3. 连接监控技巧

-- 实时查看连接状态
SHOW PROCESSLIST;

-- 查看认证失败记录
SELECT * FROM performance_schema.host_cache;

🌟 胜利宣言:成功解决后的检查清单

  1. ✅ 命令行使用api_user能成功登录MySQL
  2. ✅ 应用日志中不再出现Access denied错误
  3. SHOW GRANTS显示正确的权限配置
  4. ✅ 数据库连接测试程序返回成功
  5. ✅ 应用功能恢复正常运行

当最后一个✅被打上时,恭喜你!你不仅解决了一个技术难题,更获得了数据库连接领域的实战经验。记住:每一个错误都是成为专家的阶梯!

本文解决的不是一个简单的报错,而是一场关于权限、认证和信任的数据库外交谈判。下次当数据库大门紧闭时,你将不再是敲门人,而是手持万能钥匙的管理者!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐