MySQL 告警举例(商业版)

夜莺 v9 MySQL 数据源告警举例:以打车订单业务为例,展示如何用告警表达式语法表达常见 SQL 业务告警场景。

[PLUS] MySQL 作为告警数据源是夜莺企业版(PLUS)独有功能。

概述

MySQL 告警 = 直接用 SQL 查业务库做告警判定 — 不用把业务数据先 export 成 metric,省去采集层。

本文以一个打车订单业务为例,演示如何把 告警表达式语法 应用到 MySQL 数据源的常见场景。

适用场景:

  • 业务实时监控:订单成功率、退款率、客单价异常等指标,数据直接在业务库里;
  • 数据完整性告警:表数据 N 分钟未更新就告警;
  • 业务异常状态扫描:按订单状态/异常等级筛选触发告警。

阅读前必读

本文假设你已经了解:

业务表结构

假设业务库 taxi_service,订单表 orders

字段 含义 取值
order_id 订单 ID 自增
passenger_name 乘客姓名 字符串
driver_name 司机姓名 字符串
status 订单状态 Payment Successful / Order Canceled
abnormal_status 异常等级 No Abnormality / Low Level Abnormality / Medium Level Abnormality / High Level Abnormality
created_at 创建时间 timestamp
updated_at 更新时间 timestamp
completed_at 完成时间 timestamp
order_amount 订单金额 float
order_duration 订单时长(分钟) int

1. 算术运算

1.1 单查询条件

目标:最近 3 天的支付成功订单平均金额 < 60 触发告警。

-- $A
SELECT AVG(order_amount) AS avg_successful_payments
FROM orders
WHERE status = 'Payment Successful'
  AND created_at > DATE_SUB(NOW(), INTERVAL 3 DAY);

告警表达式

$A.avg_successful_payments < 60

1.2 多查询条件优先级

目标:近 3 天取消订单金额占总金额 > 5% 触发告警。

-- $A:成功订单金额
SELECT SUM(order_amount) AS total_successful_payments
FROM orders WHERE status = 'Payment Successful';

-- $B:取消订单金额
SELECT SUM(order_amount) AS total_canceled_orders
FROM orders WHERE status = 'Order Canceled';

告警表达式

$B.total_canceled_orders / ($A.total_successful_payments + $B.total_canceled_orders) * 100 > 5

2. 关系运算符

目标:近 6 小时订单(无异常 OR 高级别异常)且取消金额 > 100 触发告警。

-- $A:6 小时取消订单按异常等级分组
SELECT status, abnormal_status, SUM(order_amount) AS total_order_amount
FROM orders
WHERE status = 'Order Canceled'
  AND created_at > DATE_SUB(NOW(), INTERVAL 6 HOUR)
GROUP BY status, abnormal_status;

告警表达式

$A.status == 'Order Canceled' && $A.abnormal_status == "No Abnormality" && $A.total_order_amount > 100
||
$A.status == 'Order Canceled' && $A.abnormal_status == "High Level Abnormality" && $A.total_order_amount > 100

3. 逻辑运算符(AND / OR 组合)

目标:昨日取消订单量 > 前日 AND 昨日成功订单占比前日 < 60% 触发告警。

-- $A:昨日数据
-- $B:前日数据

告警表达式

$A.failed_orders > $B.failed_orders && $A.successful_orders / $B.successful_orders < 0.6

4. 集合运算(in / not in)

目标:司机 Driver13 / Driver33 任一订单金额 > 1000 或订单数 > 50 触发告警。

-- $A:按司机分组
SELECT driver_name, COUNT(*) AS counts, SUM(order_amount) AS total_order_amount
FROM orders GROUP BY driver_name;

告警表达式

($A.driver_name in ["Driver13", "Driver33"] && $A.total_order_amount > 1000)
||
($A.driver_name in ["Driver13", "Driver33"] && $A.counts > 50)

in精确匹配数组成员,不是模糊匹配。要做"姓名包含" 用 contains

5. 字符串包含(contains)

目标:司机姓名包含 “Driver9” 且订单总金额 > 3000 触发告警(关键词可以是 error code)。

告警表达式

$A.driver_name contains "Driver9" && $A.total_order_amount > 3000

适合含一类错误关键字的所有项告警,比如 $A.error_code contains "TIMEOUT"

6. 正则匹配(matches)

目标:订单异常状态匹配 ^.* Level Abnormality$ 正则且 count > 55 触发告警(覆盖 Low/Medium/High 三个级别)。

告警表达式

$A.abnormal_status matches ".* Level Abnormality$" && $A.total_counts > 55

7. 值范围(between)

目标:订单金额在 50-100 区间的单数 > 1 触发告警。

告警表达式

$A.total_counts > 1 && between($A.order_amount, [50, 100])

between 闭区间。仅适用数值类型,字符串区间不支持。

8. 时间戳运算(数据新鲜度)

目标:表数据超过 60s 未更新触发告警(数据停止上报)。

-- $A:最新一条数据的时间戳
SELECT MAX(UNIX_TIMESTAMP(created_at)) AS create_at FROM orders;

告警表达式

now().Unix() - $A.create_at > 60

时间戳仅支持加减,不能乘除。

常见问题

Q1:MySQL 数据源每多久跑一次查询?会不会压垮业务库?

A:由告警规则的"执行频率"决定(默认 15s)。核心业务库强烈建议:

  • 给 n9e 用单独的只读账号
  • 把执行频率降到 1m+;
  • 用 SQL LIMIT 限制返回行数;
  • 复杂查询前提前看 explain。

Q2:SQL 返回的列怎么映射成 $A.字段名

A:告警规则的"查询条件"里有"值字段"和"标签字段"两个配置:

  • 值字段:选 SQL 结果的某列作为 $A.xxx 引用的 xxx;
  • 标签字段:选 SQL 结果的某些列作为告警事件的标签(影响通知里能引用哪些维度)。

如 SQL SELECT product, count(*) AS cnt FROM ...,值字段选 cnt,标签字段选 product,表达式里就是 $A.cnt

Q3:能不能在 SQL 里用变量(如时间范围)?

A:可以。SQL 输入框里支持模板变量,常用 {{ time_now }} / {{ time_range }} 占位。具体支持的占位符见 MySQL 查询配置 文档。

Q4:MySQL 告警和 Prometheus 告警在表达式上有区别吗?

A:表达式完全一致(同一套语法)。区别只在:

  • 查询语言:Prometheus 用 PromQL;MySQL 用 SQL;
  • 数据形态:PromQL 自带时间序列;MySQL 是表,需要值字段 + 标签字段配置才转成"伪时序"。

理解了一种数据源后,另一种只是查询语言不同。

参考资料

更新时间 2026-05-20

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云