提交 25e4441f authored 作者: 陈泽健's avatar 陈泽健

refactor(server): 重构MySQL深度检测逻辑

- 将原有的PowerShell直接执行MySQL命令改为上传并执行独立的Shell脚本
- 新增mysql_depth_check.sh脚本用于处理MySQL性能指标检测
- 通过pscp上传检测脚本到远程服务器执行以提高执行效率
- 保留所有原有的MySQL监控指标包括QPS、TPS、死锁、缓存命中率等
- 添加对脚本执行结果的解析和错误处理机制
- 增加临时脚本清理功能避免残留文件积累
上级 c912a627
...@@ -154,7 +154,10 @@ ...@@ -154,7 +154,10 @@
"Bash(powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ' *)", "Bash(powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ' *)",
"Bash(awk '/Add-Issue.*检测到/ && !/OOM/ && !/只读/ && !/zombieCount/ && !/coreCount/ && !/磁盘错误/ && !/失败服务/' \"C:\\\\Users\\\\UBAINS\\\\Desktop\\\\Test\\\\check_server_health.ps1\")", "Bash(awk '/Add-Issue.*检测到/ && !/OOM/ && !/只读/ && !/zombieCount/ && !/coreCount/ && !/磁盘错误/ && !/失败服务/' \"C:\\\\Users\\\\UBAINS\\\\Desktop\\\\Test\\\\check_server_health.ps1\")",
"Bash(powershell.exe *)", "Bash(powershell.exe *)",
"Bash(2S)" "Bash(2S)",
"Bash(chmod +x \"C:/Users/UBAINS/Desktop/Test/test_mysql.sh\")",
"Bash(cd \"E:\\\\\\\\GithubData\\\\\\\\ubains-module-test\\\\\\\\AuxiliaryTool\\\\\\\\ScriptTool\\\\\\\\新服务自检\")",
"Bash(sed -i '1914,1985d' check_server_health.ps1)"
] ]
} }
} }
...@@ -1911,182 +1911,187 @@ function Test-MySQLStatus { ...@@ -1911,182 +1911,187 @@ function Test-MySQLStatus {
} }
} }
# 运行时间
$uptime = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE `\"Uptime`\";' 2>&1" -Timeout 10
if ($uptime -match "Uptime\s+(\d+)") {
$uptimeSeconds = [int]$Matches[1]
$uptimeDays = [Math]::Floor($uptimeSeconds / 86400)
$results += [PSCustomObject]@{
Name = "MySQL运行时间"
Value = "$uptimeDays 天"
Threshold = "-"
Status = "正常"
Message = "MySQL服务运行时间"
}
}
# 连接数统计
$connections = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE `\"Threads_connected`\";' 2>&1" -Timeout 10
if ($connections -match "Threads_connected\s+(\d+)") {
$currentConn = [int]$Matches[1]
$maxConn = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW VARIABLES LIKE `\"max_connections`\";' 2>&1" -Timeout 10
if ($maxConn -match "max_connections\s+(\d+)") {
$maxConnVal = [int]$Matches[1]
$connPercent = ($currentConn / $maxConnVal) * 100
$connStatus = Get-StatusByThreshold -Value "$connPercent" -WarningThreshold "80" -CriticalThreshold "90"
$result = [PSCustomObject]@{
Name = "MySQL连接数"
Value = "$currentConn / $maxConnVal ({0:N1}%)" -f $connPercent
Threshold = ">80%"
Status = $connStatus
Message = "当前连接数 / 最大连接数"
}
$results += $result
if ($connStatus -ne "正常") {
Add-Issue -Message ("MySQL连接使用率过高: {0:N1}%" -f $connPercent) -Level $connStatus
}
}
}
# 慢查询数量
$slowQuery = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW GLOBAL STATUS LIKE `\"Slow_queries`\";' 2>&1" -Timeout 10
if ($slowQuery -match "Slow_queries\s+(\d+)") {
$slowCount = [int]$Matches[1]
$slowStatus = Get-StatusByThreshold -Value "$slowCount" -WarningThreshold "100" -CriticalThreshold "1000000"
$result = [PSCustomObject]@{
Name = "MySQL慢查询"
Value = "$slowCount 个"
Threshold = ">100"
Status = $slowStatus
Message = "累计慢查询数量"
}
$results += $result
if ($slowStatus -ne "正常") {
Add-Issue -Message "MySQL慢查询过多: $slowCount" -Level $slowStatus
}
}
# ========== MySQL深度检测 ========== # ========== MySQL深度检测 ==========
# QPS统计 (每秒查询数) Write-Log "开始MySQL深度检测..." "INFO"
$qpsQuery = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW GLOBAL STATUS LIKE \"Questions\";' 2>&1" -Timeout 10
if ($qpsQuery -match "Questions\s+(\d+)") { # 使用pscp上传shell脚本到服务器
$questions = [long]$Matches[1] $localScriptPath = Join-Path $PSScriptRoot "mysql_depth_check.sh"
$uptimeSec = $uptimeSeconds $remoteScriptPath = "/tmp/mysql_depth_check_$pid.sh"
if ($uptimeSec -gt 0) {
$qps = [Math]::Round($questions / $uptimeSec, 2) if (Test-Path $localScriptPath) {
$results += [PSCustomObject]@{ $pscpPath = Join-Path $PSScriptRoot "pscp.exe"
Name = "MySQL QPS" if (Test-Path $pscpPath) {
Value = "$qps" # 使用pscp上传脚本
Threshold = "-" $pscpArgs = @(
Status = "正常" "-P", $script:Port,
Message = "每秒查询数 (Questions / Uptime)" "-pw", $script:Password,
} $localScriptPath,
} "$($script:Username)@$($script:HostName):$remoteScriptPath"
} )
& $pscpPath @pscpArgs 2>&1 | Out-Null
# TPS统计 (每秒事务数)
$tpsCommit = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW GLOBAL STATUS LIKE \"Com_commit\";' 2>&1" -Timeout 10 # 执行脚本
$tpsRollback = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW GLOBAL STATUS LIKE \"Com_rollback\";' 2>&1" -Timeout 10 $execCmd = "bash $remoteScriptPath"
if ($tpsCommit -match "Com_commit\s+(\d+)" -and $tpsRollback -match "Com_rollback\s+(\d+)") { $scriptResult = Invoke-SSHCommand $execCmd -Timeout 60
$commits = [long]$Matches[1]
$rollbacks = [long]$Matches[2] # 解析结果
$totalTrans = $commits + $rollbacks Write-Log "MySQL深度检测脚本结果: $scriptResult" "DEBUG"
if ($uptimeSec -gt 0) {
$tps = [Math]::Round($totalTrans / $uptimeSec, 2) foreach ($line in $scriptResult -split "`n") {
$results += [PSCustomObject]@{ if ($line -match "^QPS:(.+)$") {
Name = "MySQL TPS" $qps = $Matches[1].Trim()
Value = "$tps" if ($qps -eq "N/A") {
Threshold = "-" $results += [PSCustomObject]@{
Status = "正常" Name = "MySQL QPS"
Message = "每秒事务数 ((Com_commit + Com_rollback) / Uptime)" Value = "N/A"
} Threshold = "-"
} Status = "正常"
} Message = "每秒查询数 (暂无数据)"
}
# 死锁检测 } else {
$deadlockQuery = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE \"Innodb_deadlocks\";' 2>&1" -Timeout 10 $results += [PSCustomObject]@{
if ($deadlockQuery -match "Innodb_deadlocks\s+(\d+)") { Name = "MySQL QPS"
$deadlockCount = [int]$Matches[1] Value = $qps
$deadlockStatus = Get-StatusByThreshold -Value "$deadlockCount" -WarningThreshold "1" -CriticalThreshold "10" -HigherIsWorse $true Threshold = "-"
Status = "正常"
$result = [PSCustomObject]@{ Message = "每秒查询数 (Questions / Uptime)"
Name = "InnoDB死锁" }
Value = "$deadlockCount 个" }
Threshold = ">1警告,>10严重" }
Status = $deadlockStatus elseif ($line -match "^TPS:(.+)$") {
Message = "InnoDB累计死锁数量" $tps = $Matches[1].Trim()
} if ($tps -eq "N/A") {
$results += [PSCustomObject]@{
$results += $result Name = "MySQL TPS"
Value = "N/A"
if ($deadlockStatus -ne "正常") { Threshold = "-"
Add-Issue -Message "MySQL检测到死锁: $deadlockCount 个" -Level $deadlockStatus Status = "正常"
} Message = "每秒事务数 (暂无数据)"
} }
} else {
# Buffer Pool命中率 $results += [PSCustomObject]@{
$bpReads = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE \"Innodb_buffer_pool_read_requests\";' 2>&1" -Timeout 10 Name = "MySQL TPS"
$bpMisses = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE \"Innodb_buffer_pool_reads\";' 2>&1" -Timeout 10 Value = $tps
if ($bpReads -match "Innodb_buffer_pool_read_requests\s+(\d+)" -and $bpMisses -match "Innodb_buffer_pool_reads\s+(\d+)") { Threshold = "-"
$readRequests = [double]$Matches[1] Status = "正常"
$readMisses = [double]$Matches[2] Message = "每秒事务数 ((Com_commit + Com_rollback) / Uptime)"
if ($readRequests -gt 0) { }
$hitRate = [Math]::Round((($readRequests - $readMisses) / $readRequests) * 100, 2) }
$bpStatus = Get-StatusByThreshold -Value "$hitRate" -WarningThreshold "90" -CriticalThreshold "95" -HigherIsWorse $false }
elseif ($line -match "^DEADLOCKS:(\d+)$") {
$result = [PSCustomObject]@{ $deadlocks = [int]$Matches[1]
Name = "Buffer Pool命中率" $deadlockStatus = Get-StatusByThreshold -Value "$deadlocks" -WarningThreshold "1" -CriticalThreshold "10" -HigherIsWorse $true
Value = "$hitRate%" $results += [PSCustomObject]@{
Threshold = ">95%警告,<90%严重" Name = "InnoDB死锁"
Status = $bpStatus Value = "$deadlocks 个"
Message = "缓冲池命中率" Threshold = ">1警告,>10严重"
} Status = $deadlockStatus
Message = "InnoDB累计死锁数量"
$results += $result }
if ($deadlockStatus -ne "正常") {
if ($bpStatus -ne "正常") { Add-Issue -Message "MySQL检测到死锁: $deadlocks 个" -Level $deadlockStatus
Add-Issue -Message "Buffer Pool命中率过低: $hitRate%" -Level $bpStatus }
}
elseif ($line -match "^BUFFER_POOL_HIT_RATE:(.+)$") {
$hitRate = $Matches[1].Trim()
if ($hitRate -eq "N/A") {
$results += [PSCustomObject]@{
Name = "Buffer Pool命中率"
Value = "N/A"
Threshold = "-"
Status = "正常"
Message = "缓冲池命中率(暂无数据)"
}
} else {
$bpStatus = Get-StatusByThreshold -Value "$hitRate" -WarningThreshold "90" -CriticalThreshold "95" -HigherIsWorse $false
$results += [PSCustomObject]@{
Name = "Buffer Pool命中率"
Value = "$hitRate%"
Threshold = "<90%警告,<95%严重"
Status = $bpStatus
Message = "缓冲池命中率"
}
if ($bpStatus -ne "正常") {
Add-Issue -Message "Buffer Pool命中率过低: $hitRate%" -Level $bpStatus
}
}
}
elseif ($line -match "^CACHE_HIT_RATE:(.+)$") {
$cacheHitRate = $Matches[1].Trim()
if ($cacheHitRate -eq "N/A") {
$results += [PSCustomObject]@{
Name = "表缓存命中率"
Value = "N/A"
Threshold = "-"
Status = "正常"
Message = "表打开缓存命中率(暂无数据)"
}
} else {
$results += [PSCustomObject]@{
Name = "表缓存命中率"
Value = "$cacheHitRate%"
Threshold = "-"
Status = "正常"
Message = "表打开缓存命中率"
}
}
}
elseif ($line -match "^UPTIME_DAYS:(.+)$") {
$uptimeDays = $Matches[1].Trim()
if ($uptimeDays -ne "N/A") {
$results += [PSCustomObject]@{
Name = "MySQL运行时间"
Value = "$uptimeDays 天"
Threshold = "-"
Status = "正常"
Message = "MySQL服务运行时间"
}
}
}
elseif ($line -match "^CONNECTIONS:(.+)$") {
$connInfo = $Matches[1].Trim()
if ($connInfo -ne "N/A" -and $connInfo -match "^(\d+)/(\d+)/([\d.]+)$") {
$currentConn = $Matches[1]
$maxConn = $Matches[2]
$connPercent = $Matches[3]
$connStatus = Get-StatusByThreshold -Value "$connPercent" -WarningThreshold "80" -CriticalThreshold "90"
$results += [PSCustomObject]@{
Name = "MySQL连接数"
Value = "$currentConn / $maxConn ($connPercent%)"
Threshold = ">80%"
Status = $connStatus
Message = "当前连接数 / 最大连接数"
}
if ($connStatus -ne "正常") {
Add-Issue -Message "MySQL连接使用率过高: $connPercent%" -Level $connStatus
}
}
}
elseif ($line -match "^SLOW_QUERIES:(\d+)$") {
$slowCount = [int]$Matches[1]
$slowStatus = Get-StatusByThreshold -Value "$slowCount" -WarningThreshold "100" -CriticalThreshold "1000000"
$results += [PSCustomObject]@{
Name = "MySQL慢查询"
Value = "$slowCount 个"
Threshold = ">100"
Status = $slowStatus
Message = "累计慢查询数量"
}
if ($slowStatus -ne "正常") {
Add-Issue -Message "MySQL慢查询过多: $slowCount" -Level $slowStatus
}
}
} }
}
}
# 表缓存命中率 # 清理临时脚本
$tableOpens = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE \"Opened_tables\";' 2>&1" -Timeout 10 $null = Invoke-SSHCommand "rm -f $remoteScriptPath" -Timeout 10
$tableOpenCacheHits = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE \"Table_open_cache_hits\";' 2>&1" -Timeout 10 } else {
$tableOpenCacheMisses = Invoke-SSHCommand "docker exec umysql mysql -uroot -p'$MYSQL_PASSWORD' -e 'SHOW STATUS LIKE \"Table_open_cache_misses\";' 2>&1" -Timeout 10 Write-Log "pscp.exe未找到,跳过MySQL深度检测" "WARN"
if ($tableOpenCacheHits -match "Table_open_cache_hits\s+(\d+)" -and $tableOpenCacheMisses -match "Table_open_cache_misses\s+(\d+)") {
$cacheHits = [double]$Matches[1]
$cacheMisses = [double]$Matches[2]
$totalCacheAccess = $cacheHits + $cacheMisses
if ($totalCacheAccess -gt 0) {
$cacheHitRate = [Math]::Round(($cacheHits / $totalCacheAccess) * 100, 2)
$results += [PSCustomObject]@{
Name = "表缓存命中率"
Value = "$cacheHitRate%"
Threshold = "-"
Status = "正常"
Message = "表打开缓存命中率"
}
}
} elseif ($tableOpens -match "Opened_tables\s+(\d+)") {
# 兼容旧版本MySQL,显示表打开次数
$openedTables = [int]$Matches[1]
$results += [PSCustomObject]@{
Name = "表打开次数"
Value = "$openedTables"
Threshold = "-"
Status = "正常"
Message = "表缓存未命中的打开次数"
} }
} else {
Write-Log "mysql_depth_check.sh脚本未找到,跳过深度检测" "WARN"
} }
# ========== 数据库列表 ========== # ========== 数据库列表 ==========
......
#!/bin/bash
# MySQL深度检测脚本
# 使用方法: ./mysql_depth_check.sh
MYSQL_PASSWORD="dNrprU&2S"
CONTAINER="umysql"
# 运行时间
UPTIME=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW STATUS LIKE 'Uptime';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$UPTIME" ] && [ "$UPTIME" -gt 0 ]; then
UPTIME_DAYS=$((UPTIME / 86400))
echo "UPTIME_DAYS:$UPTIME_DAYS"
else
echo "UPTIME_DAYS:N/A"
fi
# 连接数
THREADS_CONNECTED=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW STATUS LIKE 'Threads_connected';" 2>&1 | tail -1 | awk '{print $2}')
MAX_CONNECTIONS=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW VARIABLES LIKE 'max_connections';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$THREADS_CONNECTED" ] && [ -n "$MAX_CONNECTIONS" ] && [ "$MAX_CONNECTIONS" -gt 0 ]; then
CONN_PERCENT=$(awk "BEGIN {printf \"%.1f\", $THREADS_CONNECTED*100/$MAX_CONNECTIONS}")
echo "CONNECTIONS:$THREADS_CONNECTED/$MAX_CONNECTIONS/$CONN_PERCENT"
else
echo "CONNECTIONS:N/A"
fi
# 慢查询
SLOW_QUERIES=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Slow_queries';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$SLOW_QUERIES" ]; then
echo "SLOW_QUERIES:$SLOW_QUERIES"
else
echo "SLOW_QUERIES:0"
fi
# QPS统计
QUESTIONS=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Questions';" 2>&1 | tail -1 | awk '{print $2}')
UPTIME=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW STATUS LIKE 'Uptime';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$QUESTIONS" ] && [ -n "$UPTIME" ] && [ "$UPTIME" -gt 0 ]; then
QPS=$(awk "BEGIN {printf \"%.2f\", $QUESTIONS/$UPTIME}")
echo "QPS:$QPS"
else
echo "QPS:N/A"
fi
# TPS统计
COM_COMMIT=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Com_commit';" 2>&1 | tail -1 | awk '{print $2}')
COM_ROLLBACK=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Com_rollback';" 2>&1 | tail -1 | awk '{print $2}')
if [ -n "$COM_COMMIT" ] && [ -n "$COM_ROLLBACK" ] && [ -n "$UPTIME" ] && [ "$UPTIME" -gt 0 ]; then
TOTAL_TRANS=$((COM_COMMIT + COM_ROLLBACK))
TPS=$(awk "BEGIN {printf \"%.2f\", $TOTAL_TRANS/$UPTIME}")
echo "TPS:$TPS"
else
echo "TPS:N/A"
fi
# 死锁检测
DEADLOCK_OUTPUT=$(docker exec $CONTAINER mysql -uroot -p"$MYSQL_PASSWORD" -e "SHOW GLOBAL STATUS LIKE 'Innodb_deadlocks';" 2>&1 | grep -v Warning)
if [ -n "$DEADLOCK_OUTPUT" ] && [ "$DEADLOCK_OUTPUT" != "" ]; then
DEADLOCKS=$(echo "$DEADLOCK_OUTPUT" | awk 'NF>=2 {print $2}')
if [ -z "$DEADLOCKS" ]; then
DEADLOCKS=0
fi
else
DEADLOCKS=0
fi
echo "DEADLOCKS:$DEADLOCKS"
# Buffer Pool命中率
BUFFER_POOL_RESULT=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -e "SELECT (1 - (SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_reads') / (SELECT variable_value FROM performance_schema.global_status WHERE variable_name = 'Innodb_buffer_pool_read_requests')) * 100 AS hit_ratio;" 2>&1 | grep -v Warning | tail -1)
if [ -n "$BUFFER_POOL_RESULT" ] && [[ "$BUFFER_POOL_RESULT" =~ ^[0-9]+\.?[0-9]*$ ]]; then
HIT_RATE=$(awk "BEGIN {printf \"%.2f\", $BUFFER_POOL_RESULT}")
echo "BUFFER_POOL_HIT_RATE:$HIT_RATE"
else
echo "BUFFER_POOL_HIT_RATE:N/A"
fi
# 表缓存命中率
OPEN_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW GLOBAL STATUS LIKE 'Open_tables';" 2>/dev/null | awk '{print $2}')
OPENED_TABLES=$(docker exec -e MYSQL_PWD="$MYSQL_PASSWORD" $CONTAINER mysql -uroot -N -e "SHOW GLOBAL STATUS LIKE 'Opened_tables';" 2>/dev/null | awk '{print $2}')
# 验证数值
if [[ "$OPEN_TABLES" =~ ^[0-9]+$ ]] && [[ "$OPENED_TABLES" =~ ^[0-9]+$ ]]; then
if [ "$OPENED_TABLES" -eq 0 ]; then
# 没有重新打开过表,缓存命中100%
echo "CACHE_HIT_RATE:100.00"
elif [ "$OPEN_TABLES" -gt 0 ]; then
# 表缓存命中率 = Open_tables / (Open_tables + Opened_tables) × 100
# Opened_tables表示需要重新打开表的次数(缓存未命中)
TOTAL_OPENS=$((OPEN_TABLES + OPENED_TABLES))
CACHE_HIT_RATE=$(awk "BEGIN {printf \"%.2f\", ($OPEN_TABLES * 100) / $TOTAL_OPENS}")
echo "CACHE_HIT_RATE:$CACHE_HIT_RATE"
else
echo "CACHE_HIT_RATE:N/A"
fi
else
echo "CACHE_HIT_RATE:N/A"
fi
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论