#!/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