数据库监控的必要性与范畴
数据库监控是系统稳定性的基石,作为核心组件,数据库的稳定性直接决定系统可用性,因此监控至关重要。当前市场上存在多种监控工具(如 Nagios、Zabbix),支持通过插件或自定义脚本实现数据库监控,用户可根据习惯选择工具与脚本语言(如 Python、Shell)
监控核心内容:
1 ) 服务可用性监控:
-
仅检测进程或端口存活并不充分,需通过网络连接数据库并执行简单查询(如
SELECT 1)验证实际可用性 -
超越进程/端口检查:需建立真实数据库连接并执行基础查询
-
监控指标:连接成功率、响应延迟、简单查询执行状态
sql/* 基础健康检查SQL */ SELECT 1; /* 连接池状态检查 */ SHOW STATUS LIKE 'Threads_connected';
2 )性能监控:
-
QPS(每秒查询量)、TPS(每秒事务量)、并发线程数(注意:并发线程指同时处理的 SQL 请求数,通常远小于连接数)
-
并发线程数:活跃工作线程(非连接数)
sql/* 关键性能指标查询 */ SHOW GLOBAL STATUS WHERE Variable_name IN ('Queries','Com_commit','Com_rollback','Threads_running');InnoDB阻塞监控:
sql/* 阻塞会话检测 */ SELECT bl.trx_mysql_thread_id AS blocking_id, wt.trx_mysql_thread_id AS waiting_id, wt.trx_query AS waiting_query FROM information_schema.innodb_lock_waits w JOIN information_schema.innodb_trx bl ON bl.trx_id = w.blocking_trx_id JOIN information_schema.innodb_trx wt ON wt.trx_id = w.requesting_trx_id;简单真相:
sql/* 检测阻塞事务 */ SELECT waiting_trx_id, blocking_trx_id, waiting_query, blocking_query FROM sys.innodb_lock_waits; -- 依赖sys schema
3 )主从复制监控:
-
链路状态、延迟检测及数据一致性验证
-
复制链路状态(IO/SQL线程运行状态)
-
主从延迟(Seconds_Behind_Master)
-
数据一致性校验
sql/* 主从状态检查 */ SHOW SLAVE STATUS\G /* 延迟检测 */ SELECT NOW() - MAX(create_time) AS replication_delay FROM mysql.slave_relay_log_info; /* 查看复制状态 */ SHOW REPLICA STATUS\G /* 关键字段:Replica_IO_Running, Replica_SQL_Running, Seconds_Behind_Master */
4 )服务器资源监控:
- 磁盘空间(重点监控数据库专用分区,避免因日志或数据目录占满导致服务中断)、CPU、内存、SWAP 及网络 I/O(通用指标本文不赘述)
关键风险点:
- 磁盘空间监控:数据目录/日志分区容量(即使服务器总空间充足)
- 容量规划原则:数据目录需独立分区并设置阈值告警
示例1
sql
/* 表空间监控 */
SELECT
table_schema AS `Database`,
SUM(data_length + index_length) / 1024 / 1024 AS `Size_MB`
FROM information_schema.TABLES
GROUP BY table_schema;
示例2
sql
/* 查看表空间使用(InnoDB) */
SELECT table_schema, table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.TABLES
ORDER BY size_mb DESC;
其他核心资源:
- CPU利用率(尤其user态占比)
- 内存使用(含Swap交换趋势)
- 网络I/O(连接数、流量峰值)
关键细节:数据库专用分区空间不足是常见故障点。即使服务器总磁盘空间充足,若分配给 MySQL 数据/日志目录的分区过小,仍会导致服务不可用
数据库可用性监控实现方案
1 ) 网络连接验证
仅本地连接成功不能确保远程网络可用(受防火墙、TCP 连接数限制影响)。需通过以下方式验证:
-
mysqladmin ping命令:bashmysqladmin -u monitor_user -p'password' -h 192.168.1.100 ping建立监控专用账号,循环检测多台服务器,通过返回状态判断连通性。
-
Telnet 端口检测(手动测试):
bashtelnet 192.168.1.100 3306 -
模拟应用连接(推荐):
编写代码模拟真实应用连接方式(如特定驱动版本),规避因客户端兼容性问题导致的隐蔽故障。
2 ) 读写服务验证
-
检查
read_only参数:
主库必须关闭read_only;主从切换后需确认新主库此参数为OFF。 -
轻量级读写测试:
定时对监控表执行简单操作(如UPDATE monitor_table SET check_time=NOW()),避免产生额外负载。 -
最低成本读验证:
执行无依赖查询SELECT @@version,兼容所有 MySQL 版本 -
参考:
sql-- 检查读能力 SELECT @@version; -- 写入测试(示例) INSERT INTO monitor_table (id) VALUES (1) ON DUPLICATE KEY UPDATE id=1;
3 ) 连接数阈值监控
- 关键变量:
max_connections:最大允许连接数Threads_connected:当前连接数
连接数突增(如缓存失效或阻塞引发)可能导致连接耗尽,监控方法:
-
获取配置参数:
sqlSHOW VARIABLES LIKE 'max_connections'; -- 最大连接数 # 或 SHOW GLOBAL VARIABLES LIKE 'max_connections'; -
实时状态检测:
sqlSHOW GLOBAL STATUS LIKE 'Threads_connected'; -- 当前连接数 # 或 SHOW GLOBAL STATUS LIKE 'Threads_connected'; -
报警规则:
(Threads_connected / max_connections) > 80%时触发告警。
数据库性能监控关键指标
性能监控需持续记录数据趋势,核心指标如下:
1 ) QPS & TPS 计算
-
QPS(每秒查询量):
sqlQPS = (Queries₂ - Queries₁) / 时间间隔 -- Queries 取自 SHOW GLOBAL STATUS 的输出 -
TPS(每秒事务量):
sqlTPS = [(Com_insert₂ + Com_update₂ + Com_delete₂) - (Com_insert₁ + Com_update₁ + Com_delete₁)] / 时间间隔
2 ) 并发线程监控
监控状态变量:
sql
SHOW GLOBAL STATUS LIKE 'Threads_running'; -- 实时并发数
并发量突增可能预示阻塞或缓存雪崩,需结合 CPU 使用率分析
3 ) InnoDB 阻塞监控
MyISAM 引擎缺乏原生锁监控,建议迁移至 InnoDB。InnoDB 阻塞检测 SQL:
sql
SELECT
r.trx_id AS waiting_trx_id,
r.trx_mysql_thread_id AS waiting_thread_id,
r.trx_query AS waiting_query,
b.trx_id AS blocking_trx_id,
b.trx_mysql_thread_id AS blocking_thread_id,
b.trx_query AS blocking_query,
TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) AS wait_time_sec
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id
WHERE TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) > 60; -- 阻塞超时阈值(秒)
注意:若阻塞事务已完成,可能无法捕获原始 SQL,需结合日志分析
4 ) MySQL 主从复制监控详解
4.1 复制链路状态监控
依赖 SHOW SLAVE STATUS 输出:
sql
SHOW SLAVE STATUS\G
关键字段:
Slave_IO_Running:I/O 线程状态(必须为Yes)Slave_SQL_Running:SQL 线程状态(必须为Yes)
任一状态异常即触发告警
4.2 复制延迟精确检测
Seconds_Behind_Master 不准确(网络中断时可能误判)。推荐方案:
-
主库获取二进制日志位置:
sql-- 主库执行 SHOW MASTER STATUS; -- File: mysql-bin.000001, Position: 154 -- 从库执行 SHOW SLAVE STATUS; -- 对比 Relay_Master_Log_File 和 Exec_Master_Log_Pos -
从库对比同步进度:
sqlSELECT relay_master_log_file, exec_master_log_pos FROM performance_schema.replication_applier_status_by_worker; -
判断延迟:
- 文件名不同:存在大延迟
- 文件名相同但 Position 差距大:需告警
4.3 数据一致性校验
使用 Percona Toolkit 的 pt-table-checksum:
bash
pt-table-checksum \
--user=monitor_user \
--password='password' \
--databases=mydatabase \
--replicate=test.checksum # # 在test库创建校验表
要求:主库账号需具备 SELECT、PROCESS、SUPER 权限
操作说明:
-
主库执行命令,在
test库创建checksum表存储校验结果。 -
工具自动对比主从库数据差异。
-
需配置监控账号权限:
sqlGRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'monitor_user'@'%';
4.4 服务器资源监控补充
- 磁盘空间:重点监控数据目录(如
/var/lib/mysql)和日志分区 - 其他资源:
- CPU 使用率(
top或vmstat) - 内存与 Swap 使用(
free -m) - 网络 I/O(
iftop或nload)
- CPU 使用率(
监控实施补充说明
1 ) 工具选择灵活性:
-
开发者可通过Shell、Python等编写脚本,集成到Zabbix/Nagios中
-
NestJS监控端点示例(获取数据库状态):
typescriptimport { Controller, Get } from '@nestjs/common'; import { Connection } from 'mysql2/promise'; @Controller('monitor') export class MonitorController { constructor(private connection: Connection) {} @Get('status') async getDbStatus() { const [rows] = await this.connection.query('SHOW GLOBAL STATUS'); const qps = rows.find(row => row.Variable_name === 'Queries').Value; return { status: 'OK', qps }; } }
2 ) 性能优化关联性:
- 查询性能监控需结合执行计划分析(
EXPLAIN),但本文不重复展开
SQL 示例
1 ) SQL 监控脚本关键总结
sql
-- 检查连接数
SHOW GLOBAL STATUS WHERE Variable_name = 'Threads_connected';
-- 获取 InnoDB 锁阻塞
SELECT * FROM information_schema.innodb_lock_waits;
-- 主从状态检查
SHOW SLAVE STATUS\G;
/* 综合健康检查 */
SELECT
(SELECT VARIABLE_VALUE FROM performance_schema.global_status
WHERE VARIABLE_NAME='Uptime') AS uptime,
(SELECT SUM(VARIABLE_VALUE) FROM performance_schema.global_status
WHERE VARIABLE_NAME IN ('Com_select','Com_insert','Com_update','Com_delete')) AS qps,
(SELECT VARIABLE_VALUE FROM performance_schema.global_status
WHERE VARIABLE_NAME='Threads_running') AS active_threads;
总结:
- MySQL 监控需覆盖 可用性、性能、复制、资源四维度
- 通过工具与自定义脚本结合,精准捕获异常(如阻塞、延迟),并结合阈值告警实现主动运维
- 避免因磁盘占满、连接超限等"小问题"引发服务中断
Nestjs 工程实例
1 )方案1
ts
import { Controller, Get } from '@nestjs/common';
import { execSync } from 'child_process';
@Controller('monitor')
export class DbMonitorController {
@Get('qps')
getQPS(): number {
const prevQueries = this.getStatusVariable('Queries');
setTimeout(() => {
const currQueries = this.getStatusVariable('Queries');
return (currQueries - prevQueries) / 5; // 假设5秒间隔
}, 5000);
}
private getStatusVariable(name: string): number {
const output = execSync(`mysql -u root -p[密码] -e "SHOW GLOBAL STATUS LIKE '${name}'"`);
return parseInt(output.toString().split('\t')[1]);
}
}
2 )方案2
ts
// 监控端点控制器 (monitor.controller.ts)
import { Controller, Get } from '@nestjs/common';
import { MysqlService } from './mysql.service';
@Controller('monitor')
export class MonitorController {
constructor(private readonly mysqlService: MysqlService) {}
@Get('healthcheck')
async healthCheck() {
return {
status: await this.mysqlService.checkConnection(),
metrics: await this.mysqlService.getPerformanceMetrics()
};
}
}
// MySQL服务层 (mysql.service.ts)
import { Injectable } from '@nestjs/common';
import { Connection } from 'mysql2/promise';
@Injectable()
export class MysqlService {
constructor(private connection: Connection) {}
async checkConnection(): Promise<string> {
const [rows] = await this.connection.query('SELECT 1 AS status');
return rows[0].status === 1 ? 'OK' : 'DOWN';
}
async getPerformanceMetrics() {
const [qpsRes] = await this.connection.query(
`SHOW GLOBAL STATUS WHERE Variable_name IN ('Queries','Threads_running')`
);
return {
queries: qpsRes.find(r => r.Variable_name === 'Queries').Value,
active_threads: qpsRes.find(r => r.Variable_name === 'Threads_running').Value
};
}
}
总结
数据库监控需覆盖 可用性、性能、复制、资源 四个维度:
- 可用性:通过模拟连接与读写操作验证真实可用性
- 性能:聚焦 QPS/TPS 趋势、并发量及 InnoDB 阻塞
- 主从复制:链路状态、精确延迟检测(日志位置比对)及周期性数据校验
- 资源:优先确保数据库专用磁盘空间充足
实施建议:将监控脚本集成至 Prometheus + Grafana 或 Zabbix,实现可视化告警与历史数据分析
通过组合原生SQL监控与NestJS自动化端点,可构建覆盖可用性、性能、资源的三维监控体系,有效预防80%的数据库故障场景。监控脚本需以5-10分钟为周期采集数据,配合趋势分析实现异常预警