存储过程可通过查询information_schema.processlist统计活跃连接数,并联查innodb_trx与innodb_lock_waits定位锁等待;启用event scheduler实现定时执行;结合sys.schema_table_statistics监控表空间;用declare handler捕获异常并写入health_log表;需授予process权限确保访问权限。

存储过程里怎么查数据库连接数和锁等待?
健康检查第一步是确认数据库没被连接打爆或锁死。别依赖 SHOW PROCESSLIST 手动看,得让存储过程自动抓关键指标。
- 用
information_schema.PROCESSLIST查当前活跃连接:SELECT COUNT(*) FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep',注意过滤掉休眠连接,否则误报 - 查锁等待得组合
information_schema.INNODB_TRX和information_schema.INNODB_LOCK_WAITS:先找TRX_STATE = 'LOCK WAIT'的事务,再关联LOCK_TRX_ID定位阻塞源 - MySQL 5.7+ 可直接用
performance_schema.data_lock_waits,但默认关闭,得提前开:UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'wait/lock/metadata/sql/mdl'
怎么让存储过程定期跑而不靠应用层调度?
靠外部脚本调用太脆弱,容易漏跑或重复跑。MySQL 原生事件调度器(Event Scheduler)才是正解,但默认关着。
- 先开开关:
SET GLOBAL event_scheduler = ON,并确认my.cnf里有event_scheduler=ON,否则重启就失效 - 建事件时别用
AT,用EVERY+STARTS:比如每5分钟跑一次:CREATE EVENT check_health ON SCHEDULE EVERY 5 MINUTE STARTS NOW() DO CALL sp_db_health_check() - 事件名别带特殊字符,否则删的时候会报错:
DROP EVENT IF EXISTS check_health比DROP EVENT `check-health`安全得多
存储过程里怎么写可复用的表空间监控逻辑?
磁盘满是高频故障,但 INFORMATION_SCHEMA.TABLES 只给行数,不给真实大小。得绕到 INFORMATION_SCHEMA.STATISTICS 和文件系统层面。
-
DATA_LENGTH + INDEX_LENGTH是估算值,实际要看innodb_file_per_table=ON下每个表的.ibd文件大小,用sys.schema_table_statistics(MySQL 8.0+)更准 - 对大表做
ANALYZE TABLE之前,先查TABLE_ROWS是否远小于AVG_ROW_LENGTH * DATA_LENGTH,差10倍以上说明统计信息严重过期 - 别在存储过程中直接执行
OPTIMIZE TABLE—— 它会锁表,改成记录告警并通知DBA,用ALTER TABLE ... ALGORITHM=INPLACE替代
为什么存储过程里的错误处理总被忽略?
健康检查失败了没报出来,等于没做。MySQL 存储过程的异常捕获机制和应用层完全不同,DECLARE HANDLER 必须显式写。
- 别只写
DECLARE EXIT HANDLER FOR SQLEXCEPTION,得加上SQLWARNING和特定错误码,比如DECLARE CONTINUE HANDLER FOR 1205(死锁)单独记日志 - 错误信息不能只
SELECT,得插入到专门的health_log表里,字段至少含:check_time、error_code、error_message、sql_state - 别用
GET DIAGNOSTICS抓完整堆栈——它在某些版本返回空,稳妥做法是把关键 SQL 包进CONCAT日志里:CONCAT('Failed on: ', @sql)
最常被跳过的其实是权限问题:存储过程以定义者权限运行,但 information_schema 视图访问受 PROCESS 权限控制,SELECT 不够,得显式 GRANT PROCESS ON *.* TO 'health_user'@'%'。











