在MySQL中可以通过触发器结合性能数据查询,实现针对数据库性能的自动报警机制,这种方式不需要依赖额外的外部监控工具,适合轻量级的性能异常感知场景。

实现基础:MySQL性能数据获取
要监控数据库性能,首先需要获取对应的性能数据,MySQL的performance_schema库提供了丰富的运行时性能统计信息,常用的性能监控相关表如下:
| 表名 | 作用 |
|---|---|
| events_statements_summary_by_digest | 统计所有SQL语句的执行耗时、次数等摘要信息,可用于慢查询监控 |
| global_status | 存储全局运行状态变量,可获取当前连接数、查询次数等指标 |
| threads | 记录当前所有线程的状态,可用于分析活跃连接情况 |
触发器与报警逻辑设计
MySQL的触发器本身不支持直接发送外部通知,因此报警逻辑通常分为两步:第一步通过触发器将性能异常记录到自定义报警表中,第二步通过定时任务读取报警表的内容并触发后续通知(如写入日志、调用外部接口等)。
步骤1:创建报警记录表
首先创建一个用于存储性能报警信息的表,结构如下:
CREATE TABLE IF NOT EXISTS db_perf_alert (
id INT PRIMARY KEY AUTO_INCREMENT,
alert_type VARCHAR(50) NOT NULL COMMENT '报警类型,如slow_query,conn_exceed',
alert_content TEXT NOT NULL COMMENT '报警具体内容',
alert_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_handled TINYINT NOT NULL DEFAULT 0 COMMENT '是否已处理,0未处理,1已处理'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库性能报警记录表';
步骤2:创建性能检查存储过程
由于触发器无法直接查询performance_schema的表,因此需要先创建存储过程,用于检查性能指标是否超标,超标则写入报警表:
DELIMITER //
CREATE PROCEDURE check_db_perf()
BEGIN
DECLARE conn_count INT;
DECLARE slow_query_count INT;
-- 获取当前连接数
SELECT VARIABLE_VALUE INTO conn_count FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Threads_connected';
-- 获取最近1分钟慢查询数量,假设慢查询阈值设置为2秒,这里统计执行时间超过2秒的语句数量
SELECT COUNT(*) INTO slow_query_count FROM performance_schema.events_statements_summary_by_digest WHERE AVG_TIMER_WAIT > 2000000000;
-- 连接数超过100则触发报警
IF conn_count > 100 THEN
INSERT INTO db_perf_alert (alert_type, alert_content) VALUES ('conn_exceed', CONCAT('当前数据库连接数超标,当前连接数:', conn_count));
END IF;
-- 慢查询数量超过10则触发报警
IF slow_query_count > 10 THEN
INSERT INTO db_perf_alert (alert_type, alert_content) VALUES ('slow_query', CONCAT('慢查询数量超标,当前慢查询数量:', slow_query_count));
END IF;
END //
DELIMITER ;
步骤3:设置定时任务触发检查
MySQL的事件调度器可以定时执行上述存储过程,实现周期性的性能检查和报警触发:
-- 开启事件调度器
SET GLOBAL event_scheduler = ON;
-- 创建每分钟执行一次的性能检查事件
CREATE EVENT IF NOT EXISTS ev_check_db_perf
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP
DO
BEGIN
CALL check_db_perf();
END;
报警后续处理
报警记录写入db_perf_alert表后,可以通过外部脚本(如Python、Shell脚本)定时读取未处理的报警记录,实现邮件、短信或者企业内部通知的发送,以下是一个简单的Python读取示例:
import pymysql
# 连接MySQL数据库
conn = pymysql.connect(
host='127.0.0.1',
user='root',
password='your_password',
database='your_db',
charset='utf8mb4'
)
cursor = conn.cursor()
# 查询未处理的报警记录
cursor.execute("SELECT id, alert_type, alert_content, alert_time FROM db_perf_alert WHERE is_handled = 0")
alerts = cursor.fetchall()
for alert in alerts:
alert_id, alert_type, alert_content, alert_time = alert
# 这里可以添加发送通知的逻辑,比如调用邮件接口、企业微信接口等
print(f"收到报警:类型{alert_type},内容{alert_content},时间{alert_time}")
# 标记报警已处理
cursor.execute("UPDATE db_perf_alert SET is_handled = 1 WHERE id = %s", (alert_id,))
conn.commit()
cursor.close()
conn.close()
注意事项
- 频繁查询
performance_schema的表会对数据库产生轻微的性能开销,建议合理设置检查周期,不要设置过短的间隔时间。 - 触发器方案适合轻量级监控场景,如果需要更全面的性能监控和复杂报警规则,建议结合专业的监控工具使用。
- 存储过程和事件的权限需要单独授予,确保执行用户有对应的
performance_schema查询权限和事件创建权限。
MySQLtriggerperformance_schema数据库监控alert修改时间:2026-06-13 22:57:21