245 lines
7.5 KiB
Bash
245 lines
7.5 KiB
Bash
#!/bin/bash
|
||
# 数据库连接诊断脚本
|
||
# 用于诊断和修复数据库连接池问题
|
||
|
||
set -e
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
log_warn() {
|
||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
# 检查数据库服务状态
|
||
check_database_service() {
|
||
log_info "检查数据库服务状态..."
|
||
|
||
if docker ps --filter "name=anxin-mysql-prod" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep anxin-mysql-prod; then
|
||
log_success "✓ MySQL容器正在运行"
|
||
|
||
# 检查健康状态
|
||
local health=$(docker inspect anxin-mysql-prod --format='{{.State.Health.Status}}' 2>/dev/null || echo "unknown")
|
||
log_info "MySQL健康状态: $health"
|
||
|
||
if [[ "$health" == "healthy" ]]; then
|
||
log_success "✓ MySQL容器健康检查通过"
|
||
else
|
||
log_warn "MySQL容器健康检查未通过"
|
||
fi
|
||
else
|
||
log_error "✗ MySQL容器未运行"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 测试数据库连接
|
||
test_database_connection() {
|
||
log_info "测试数据库连接..."
|
||
|
||
if [[ -f "environments/.env.production" ]]; then
|
||
source environments/.env.production
|
||
|
||
# 测试root连接
|
||
log_info "测试root用户连接..."
|
||
if docker exec anxin-mysql-prod mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT 1;" 2>/dev/null; then
|
||
log_success "✓ root用户连接成功"
|
||
else
|
||
log_error "✗ root用户连接失败"
|
||
fi
|
||
|
||
# 测试应用用户连接
|
||
log_info "测试应用用户连接..."
|
||
if docker exec anxin-mysql-prod mysql -u"$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1;" "$DB_NAME" 2>/dev/null; then
|
||
log_success "✓ 应用用户连接成功"
|
||
else
|
||
log_error "✗ 应用用户连接失败"
|
||
fi
|
||
|
||
# 检查数据库是否存在
|
||
log_info "检查数据库是否存在..."
|
||
if docker exec anxin-mysql-prod mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;" | grep -q "$DB_NAME"; then
|
||
log_success "✓ 数据库 $DB_NAME 存在"
|
||
else
|
||
log_error "✗ 数据库 $DB_NAME 不存在"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# 检查后端服务连接配置
|
||
check_backend_connection_config() {
|
||
log_info "检查后端服务连接配置..."
|
||
|
||
if docker ps --filter "name=anxin-backend-prod" --format "{{.Names}}" | grep -q "anxin-backend-prod"; then
|
||
log_success "✓ 后端容器正在运行"
|
||
|
||
# 检查环境变量
|
||
echo "数据库连接环境变量:"
|
||
docker exec anxin-backend-prod env | grep -E "^DB_" | while read line; do
|
||
if [[ $line == *"PASSWORD"* ]]; then
|
||
echo " ${line%%=*}=[HIDDEN]"
|
||
else
|
||
echo " $line"
|
||
fi
|
||
done
|
||
|
||
# 检查网络连通性
|
||
log_info "测试容器间网络连通性..."
|
||
if docker exec anxin-backend-prod nc -z anxin-mysql 3306 2>/dev/null; then
|
||
log_success "✓ 后端容器可以连接到MySQL容器"
|
||
else
|
||
log_error "✗ 后端容器无法连接到MySQL容器"
|
||
fi
|
||
else
|
||
log_error "✗ 后端容器未运行"
|
||
fi
|
||
}
|
||
|
||
# 检查应用日志中的连接错误
|
||
check_connection_errors() {
|
||
log_info "检查应用日志中的连接错误..."
|
||
|
||
echo "最近的数据库连接错误:"
|
||
echo "----------------------------------------"
|
||
./deploy.sh logs backend -e production --tail 100 | grep -i -E "(connection|datasource|mysql|jdbc)" | tail -10 || echo "未找到相关日志"
|
||
echo "----------------------------------------"
|
||
|
||
# 检查是否有连接池相关错误
|
||
if ./deploy.sh logs backend -e production --tail 200 | grep -i "DataSourceClosedException"; then
|
||
log_error "发现数据源关闭异常"
|
||
fi
|
||
|
||
if ./deploy.sh logs backend -e production --tail 200 | grep -i "CannotGetJdbcConnectionException"; then
|
||
log_error "发现JDBC连接获取异常"
|
||
fi
|
||
}
|
||
|
||
# 修复数据库连接问题
|
||
fix_database_connection() {
|
||
log_info "尝试修复数据库连接问题..."
|
||
|
||
# 1. 重启MySQL服务
|
||
log_info "重启MySQL服务..."
|
||
./deploy.sh restart mysql -e production
|
||
sleep 10
|
||
|
||
# 2. 等待MySQL完全启动
|
||
log_info "等待MySQL服务完全启动..."
|
||
local max_attempts=30
|
||
local attempt=1
|
||
|
||
while [ $attempt -le $max_attempts ]; do
|
||
if docker exec anxin-mysql-prod mysqladmin ping -h localhost -u root -p"$MYSQL_ROOT_PASSWORD" 2>/dev/null; then
|
||
log_success "MySQL服务已就绪"
|
||
break
|
||
fi
|
||
|
||
echo "等待MySQL服务... (尝试 $attempt/$max_attempts)"
|
||
sleep 2
|
||
attempt=$((attempt + 1))
|
||
done
|
||
|
||
if [ $attempt -gt $max_attempts ]; then
|
||
log_error "MySQL服务启动超时"
|
||
return 1
|
||
fi
|
||
|
||
# 3. 重启后端服务
|
||
log_info "重启后端服务..."
|
||
./deploy.sh restart backend -e production
|
||
sleep 15
|
||
|
||
# 4. 检查修复结果
|
||
log_info "检查修复结果..."
|
||
if ./deploy.sh logs backend -e production --tail 20 | grep -i "started.*in"; then
|
||
log_success "✓ 后端服务启动成功"
|
||
else
|
||
log_warn "后端服务启动状态未知,请检查日志"
|
||
fi
|
||
}
|
||
|
||
# 显示修复建议
|
||
show_fix_suggestions() {
|
||
log_info "修复建议:"
|
||
echo "========================================"
|
||
echo "如果问题仍然存在,请尝试以下步骤:"
|
||
echo ""
|
||
echo "1. 完全重启所有服务:"
|
||
echo " ./deploy.sh down -e production"
|
||
echo " ./deploy.sh up -e production"
|
||
echo ""
|
||
echo "2. 检查数据库用户权限:"
|
||
echo " docker exec anxin-mysql-prod mysql -uroot -p"
|
||
echo " SHOW GRANTS FOR 'anxin_prod'@'%';"
|
||
echo ""
|
||
echo "3. 检查数据库配置:"
|
||
echo " docker exec anxin-mysql-prod mysql -uroot -p -e \"SHOW VARIABLES LIKE 'max_connections';\""
|
||
echo ""
|
||
echo "4. 如果是连接池配置问题,检查application-docker.yml中的Druid配置"
|
||
echo ""
|
||
echo "5. 监控资源使用情况:"
|
||
echo " docker stats anxin-mysql-prod anxin-backend-prod"
|
||
echo "========================================"
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
local action=${1:-"diagnose"}
|
||
|
||
log_info "数据库连接诊断工具"
|
||
echo "========================================"
|
||
|
||
case $action in
|
||
"diagnose")
|
||
check_database_service
|
||
echo ""
|
||
test_database_connection
|
||
echo ""
|
||
check_backend_connection_config
|
||
echo ""
|
||
check_connection_errors
|
||
echo ""
|
||
show_fix_suggestions
|
||
;;
|
||
"fix")
|
||
if [[ -f "environments/.env.production" ]]; then
|
||
source environments/.env.production
|
||
fix_database_connection
|
||
echo ""
|
||
main "diagnose"
|
||
else
|
||
log_error "未找到环境配置文件"
|
||
fi
|
||
;;
|
||
*)
|
||
echo "用法: $0 [diagnose|fix]"
|
||
echo " diagnose - 诊断数据库连接问题(默认)"
|
||
echo " fix - 尝试修复数据库连接问题"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
echo "========================================"
|
||
log_success "操作完成!"
|
||
}
|
||
|
||
# 如果脚本被直接执行
|
||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||
main "$@"
|
||
fi |