概览 — 这个页面做什么
服务 ▸ 数据库(/service/database)是一个实时监控页面,它直接连接到已注册的数据库采集器(access=database),采样负载指标并分析库表结构。每个数据库渲染为一张卡片,每张卡片都一眼呈现两条负载轴。
数据库监控围绕两条负载轴构建:
| 轴 | 要回答的问题 | 关键指标 |
|---|---|---|
| ① 并发负载 | 此刻积压了多少? | threads_running、连接饱和度(conn_pct)、等待中的查询(waiting) |
| ② 吞吐与低效 | 做了多少工作,又浪费了多少? | QPS(Δquestions/Δt)、慢查询速率(Δslow_queries/Δt) |
在此之上,它还提供库表结构分析(总容量 · 最大的库 · 最大的表 · 引擎构成)、效率评分(缓冲池缓存命中率 · 索引使用率),以及 InnoDB 内存管理区块(脏页刷新 · 检查点)。
本页面不会在目标 DB 上安装任何代理。InfraGuard 应用只是用已登记的凭据连接远端 MySQL/MariaDB,并发出
SHOW GLOBAL STATUS/information_schema查询。
何时使用
- 数据库突然变慢 — 立刻判断是连接饱和、并发飙升,还是慢查询增多。
- 连接池调优前后 — 观察
threads_connected / max_connections的饱和度随时间的变化。 - 容量规划 — 查看哪些库/表占用磁盘最多,以及引擎构成。
- 诊断 InnoDB 刷新压力 — 脏页是否在阈值之下健康循环,检查点年龄相对 redo 容量已经推进了多远。
- 缓存/索引效率评审 — 把缓冲池命中率与索引使用率作为调优依据来读。
页面布局
顶部 KPI
| KPI | 含义 |
|---|---|
| DB 数量 | 已注册的 access=database 采集器总数 |
| Up / Degraded / Down | 卡片状态(up/degraded/down)的汇总 |
| 总 QPS | 所有卡片 QPS 之和 |
| 连接数 | 所有卡片 threads_connected 之和 |
卡片头部
- 主机标签(依次取采集器
host_alias→ config.host → cred_ref 的 env 主机)。 - 驱动(
mysql/mariadb)、数据库名、运行时长、状态徽章。
① 并发负载
- 连接饱和度环形仪表 =
threads_connected / max_connections。 - Running(
threads_running)— 实际在消耗 CPU 的线程。 - Waiting(积压)(
waiting)— 处理时间超过阈值(默认 2 秒)的查询。取决于PROCESS权限,它统计的是整个服务器还是仅自身连接(范围显示在卡片上)。
② 吞吐与低效
- QPS 迷你折线 =
Δquestions / Δt(最近 60 个成功样本)。 - 慢查询速率 =
Δslow_queries / Δt,以及慢查询总数(slow_queries)。
卡片底部 — 效率 · 锁
| 指标 | 公式 | 评级 |
|---|---|---|
| 缓存命中率 | 1 − Δinnodb_buffer_pool_reads / Δinnodb_buffer_pool_read_requests |
优秀 ≥99.5% · 良好 ≥98% · 一般 ≥90% |
| 索引使用率 | Δhandler_read_key / (Δhandler_read_key + Δhandler_read_rnd_next) |
优秀 ≥90% · 良好 ≥70% · 一般 ≥40% |
| lock | innodb_row_lock_time_avg(行锁平均等待,毫秒) |
越低越好 |
每个指标标签(cache · index · lock · checkpoint)都带有讲解成因与对策的教学浮层(例如调大 innodb_buffer_pool_size、使用覆盖索引、避免间隙锁)。
库表结构分析(可折叠)
默认折叠,用 [展开] 打开。它从 information_schema.tables 汇总,显示总容量 · 表数量 · 库数量 · 按容量排名前 8 的库 · 按容量排名前 14 的表 · 引擎构成。
库表结构分析在服务器上本身就是一条慢查询(实测约 3.5 秒),因此用 30 分钟长缓存规避。调度器(
infr:collect-db)会预热缓存,所以 Web 请求总能命中。缓存为空时该区块会短暂隐藏,下一次轮询即出现。
InnoDB 内存管理(脏页刷新)
- 脏页时间序列 + “适宜值”(阈值)叠加线 — 把 MAX(
innodb_max_dirty_pages_pct)与 LWM(innodb_max_dirty_pages_pct_lwm)换算成绝对页数(不是随意取的常量,而是 InnoDB 真正开始激进刷新的那个点)。 - 检查点年龄(
Log sequence number − Last checkpoint at),以占 redo 容量的百分比表示。 - 缓冲池大小及其相对服务器 RAM 的比例(按 alias 关联的 OS 实例
mem_mb)。
卡片排列
卡片网格支持拖拽重排(SortableJS · 顺序保存到 localStorage)与 row-span 瀑布流布局。页面按 30 秒轮询刷新。
使用方法
- 先在 管理 ▸ 采集器 下注册一个
access=database采集器。填写host/port/database/username+ 密码(在采集器上以 Crypt 加密存储),或设置cred_ref = env:PREFIX来复用已有的.env凭据集。 - 打开
/service/database,已注册的数据库会以卡片列出。进入时如果最新样本超过 60 秒,会立即执行一次即时单次采样(ensureFresh)。 - 通过头部状态徽章找出有问题的 DB,再沿两条负载轴(并发/吞吐)收敛原因。
- 展开库表结构分析,查看最大的库/表(高度变化时瀑布流会自动重新布局)。
- 拖动卡片把关心的数据库置顶(顺序保存在浏览器中)。
通过 cred_ref 复用凭据
使用 cred_ref = env:PREFIX 时,下列键会从 .env 读取,因此不会有任何秘密存入 DB:
例如:env:STATS_DB → blue 服务器,env:STATS_GLORY_DB → glory 服务器。
要查看整个服务器范围的等待查询
要在整个服务器范围汇总 waiting,监控账号需要 PROCESS 权限;否则只统计它自己的连接。最小权限的监控账号:
CREATE USER 'infra_monitor'@'%' IDENTIFIED BY 'YOUR_DB_PASSWORD';
GRANT PROCESS, SELECT ON *.* TO 'infra_monitor'@'%';
FLUSH PRIVILEGES;
范围判定(是否持有
PROCESS)对每个账号是固定的,因此会缓存 1 小时。如果之后才授予该权限,会在一小时内生效(要立即生效请清除缓存)。
数据来源
源头查询(在远端 DB 上执行)
| 查询 | 用途 |
|---|---|
SHOW GLOBAL STATUS |
全部 threads · questions · slow_queries · bytes · 缓冲池 · handler · InnoDB 计数器 |
SELECT @@GLOBAL.max_connections 等 |
max_connections、InnoDB 刷新设置(1 小时缓存) |
information_schema.processlist |
等待查询数 + 范围判定 |
information_schema.tables |
库表结构分析(30 分钟缓存) |
SHOW ENGINE INNODB STATUS |
检查点年龄(LSN − 最后检查点 · 需要 PROCESS) |
SHOW GRANTS FOR CURRENT_USER() |
PROCESS 权限检测(范围) |
存储表
采样数据写入 infr_db_metric 时间序列表(迁移 000681)。累计计数器(questions/slow_queries/bytes_*)也一并保存,以便下一次采样按差值计算 QPS · 慢查询速率 · 效率评分。
infr_db_metric
collector_id host sampled_at uptime_sec
threads_connected/running/cached max_connections conn_pct
waiting waiting_scope
questions slow_queries qps slow_qps
bytes_received/sent recv_bps/sent_bps innodb_row_lock_waits
ok message raw(json: efficiency + InnoDB memory-management derivations)
不允许连接泄漏([1040] 的教训)。 每次采样都会建立一个运行时连接,并在
finally中立即DB::purge。PDO 超时(默认 5 秒)可避免 Web 请求与调度器卡在响应缓慢的远端上。一旦这条纪律被打破,共享 MySQL 的max_connections就会被耗尽,连生产环境都会受影响。
采集调度 · 门控
时间序列由 artisan 命令 infr:collect-db 填充。它执行一次即退出(不是守护进程);调度器每分钟调用一次。
# 对单个采集器立即采样一次(绕过门控)
php artisan infr:collect-db --key=db@blue --force
运维策略(管理 ▸ 运维策略 · OpsPolicy)对计划执行进行门控:
| 设置 | 默认值 | 含义 |
|---|---|---|
db_collect_mode |
economy |
economy = 仅当有控制台用户(presence)时才采集 · always = 持续采集 |
db_collect_interval_sec |
60 |
采集间隔(秒)。每分钟触发一次,但实际周期以此值为准 |
degraded/down 阈值
DbCollectorService::statusOf 通过 OpsPolicy::dbThresholds() 判定状态。
| 原因 | 条件 | 默认阈值 |
|---|---|---|
conn_saturation |
conn_pct ≥ |
80% |
high_concurrency |
threads_running ≥ |
40 |
query_backlog |
waiting ≥ |
5 |
slow_query_rate |
slow_qps ≥ |
1/秒 |
down |
没有样本/ok=false,或最新样本超过 5 分钟(stale) |
— |
只要出现任一原因 → degraded;一个都没有 → up。
访问权限
- 本页面是
infr.auth组内的只读控制台 — 最低读取级别 demo=1。 - 本页没有写入端点。目标 DB 凭据的注册/编辑在 管理 ▸ 采集器(admin=10,
level≥5门控)中进行。 - 阈值与采集模式在 管理 ▸ 运维策略(admin)中修改。
故障排查与 FAQ
卡片显示 “down”
no_credentials— config 的 host/username 为空,或cred_ref=env:PREFIX对应的 env 键缺失。stale— 最新样本超过 5 分钟。检查调度器(infr:collect-db)是否在运行;economy 模式下还要确认有控制台用户在线。- 其他消息 — 会原样显示连接失败的原因(认证被拒、主机不可达、超时)。用
php artisan infr:collect-db --key=<key> --force诊断。
QPS / 慢查询速率 / 效率评分显示 “—”
派生值是相对上一个成功样本的差值计算出来的。首次采样时、DB 重启后(uptime 变小 → 计数器重置)、或计数器回退时,数值不可信,因此保持 null (—)。从第二个样本起会正常显示。
等待查询显示“仅自身连接”
监控账号缺少全局 PROCESS 权限,因此在 information_schema.processlist 中只能看到自己的连接。用 要查看整个服务器范围的等待查询 中的 SQL 授予 PROCESS(在范围缓存过期后的一小时内生效)。
内存管理 / 检查点区块为空
- 内存管理需要
innodb_buffer_pool_pages_total(旧样本中不显示)。 - 检查点年龄从
SHOW ENGINE INNODB STATUS解析(→ 需要PROCESS)。没有该权限时,检查点线与标注会被优雅地省略。
库表结构分析先闪空再出现
analysisCached 只做缓存查找。首次进入时缓存为空,该区块隐藏;调度器预热之后,会在下一次 30 秒轮询时出现。失败只缓存 30 秒(成功缓存 30 分钟),因此瞬时错误不会被长时间钉住。
相关内容
- DB 负载与调优讲解 — lock · cache · index · checkpoint 浮层的背景知识。
- 采集器 — 注册
access=database采集器、秘密信息、cred_ref。 - 运维策略 — 采集模式 · 间隔 · degrade 阈值。
- 会话 (Redis) — 把同一套方法论应用到 Redis 的姊妹页面。
- 服务概览 — 实时服务看板上汇总 DB 卡片的地方。
- DB 采集器流水线 — 采集命令与防连接泄漏的纪律。
