在Java应用开发中,数据库连接是必不可少的一环。然而,在使用MySQL时,我们可能会遇到类似以下的错误:
Host '124.221.131.191' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'这个错误表明,MySQL服务器由于检测到过多的连接失败,自动阻止了来自该主机的连接请求。本文将深入分析该问题的原因,并提供完整的解决方案,包括如何在代码层面优化数据库连接管理。
从错误日志可以看出,Druid连接池在尝试建立MySQL连接时失败,关键错误信息如下:
java.sql.SQLException: null, message from server:
"Host '124.221.131.191' is blocked because of many connection errors;
unblock with 'mysqladmin flush-hosts'"MySQL有一个安全机制,当某个客户端(IP)在短时间内多次连接失败(默认max_connect_errors=100),MySQL会认为该主机可能存在恶意攻击或配置错误,从而自动阻止其连接。
常见触发原因:
在MySQL服务器上执行以下命令:
FLUSH HOSTS;或者使用mysqladmin命令:
mysqladmin flush-hosts -u root -pmax_connect_errors-- 查看当前值
SHOW VARIABLES LIKE 'max_connect_errors';
-- 修改(需重启MySQL或动态调整)
SET GLOBAL max_connect_errors = 1000;在application.yml或application.properties中调整Druid参数:
spring:
datasource:
url: jdbc:mysql://124.221.131.191:3306/kwan?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5 # 初始连接数
min-idle: 5 # 最小空闲连接
max-active: 20 # 最大活跃连接
max-wait: 60000 # 获取连接超时时间(毫秒)
validation-query: SELECT 1 # 连接检测SQL
test-while-idle: true # 空闲时检测连接
test-on-borrow: false # 获取连接时不检测(影响性能)
test-on-return: false # 归还连接时不检测
time-between-eviction-runs-millis: 60000 # 检测间隔
min-evictable-idle-time-millis: 300000 # 最小空闲时间try-with-resources确保连接正确关闭import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
public class UserDao {
private final DataSource dataSource;
public UserDao(DataSource dataSource) {
this.dataSource = dataSource;
}
public String getUserNameById(int id) {
String sql = "SELECT username FROM users WHERE id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1, id);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getString("username");
}
}
} catch (SQLException e) {
throw new RuntimeException("Failed to query user", e);
}
return null;
}
}使用Druid自带的监控:
@Bean
public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() {
ServletRegistrationBean<StatViewServlet> registrationBean =
new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
registrationBean.addInitParameter("loginUsername", "admin");
registrationBean.addInitParameter("loginPassword", "admin");
return registrationBean;
}访问 http://localhost:8080/druid 可查看连接池状态。
public Connection getConnectionWithRetry(DataSource dataSource, int maxRetries) {
int retryCount = 0;
while (retryCount < maxRetries) {
try {
return dataSource.getConnection();
} catch (SQLException e) {
retryCount++;
if (retryCount >= maxRetries) {
throw new RuntimeException("Failed to get connection after " + maxRetries + " retries", e);
}
try {
Thread.sleep(1000); // 1秒后重试
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted while waiting for retry", ie);
}
}
}
throw new IllegalStateException("Should not reach here");
}[mysqld]
max_connections = 200 # 最大连接数
wait_timeout = 28800 # 非交互式连接超时时间(秒)
interactive_timeout = 28800 # 交互式连接超时时间
max_connect_errors = 1000 # 调高连接错误阈值FLUSH HOSTS 或 mysqladmin flush-hosts。✅ 合理配置连接池(初始连接数不宜过大)
✅ 使用try-with-resources确保连接关闭
✅ 监控数据库连接状态(Druid监控面板)
✅ 优化MySQL服务器参数(max_connect_errors、max_connections)
通过以上方法,可以有效避免MySQL连接被阻塞的问题,提高系统的稳定性和可靠性。
📌 进一步阅读
希望本文能帮助你彻底解决MySQL连接阻塞问题!🚀