Grafana和MySQL相差8小时

背景说明

今日在用 Grafana 进行数据大屏看板制作 (数据源为 MySQL),其中有个面板是统计 “每日的用户反馈表单数量曲线图”,如图

每日用户反馈表单数量曲线图
因为要确保数据的准确性,于是进行了验证,抽样调查了其中的一个表单类型 异常反馈 的数量

select count(1) as total from user_form_request where ct >= CURRENT_DATE() and form_type = 13; 
# 执行结果为 total => 42
select count(1) as total from user_form_request where ct >= '2023-04-11 08:00:00' and form_type = 13; 
# 执行结果为 total => 32

从上面的查询结果表现来看,后者和图中统计的结果数据才对得上(均为 32),也就是说 Grafana 统计的聚合数据比实际偏移了8个小时!

问题排查

从广大的网络文章看,主要集中都是说 Grafana 时区或者 MySQL 时区设置有问题,或者两者的时区对不上!

于是,我先检查看下 Grafana 的设置,看到已经默认设置成我们 东八区

Grafana timezone setting

排除了 Grafana 时区问题,需要进一步确定 MySQL 是否也是使用 东八区

SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;

查询结果显示 SYSTEM,也即跟随服务系统的时区设置。

因为 MySQL 时区随了系统了,所以接下来需要确认服务器的时区情况

# 执行下面命令进行查询
timedatectl

# 输出结果如下
# -------------------------------------------------
      Local time: Tue 2023-04-11 23:09:27 CST
  Universal time: Tue 2023-04-11 15:09:27 UTC
        RTC time: Tue 2023-04-11 15:09:27
       Time zone: n/a (CST, +0800)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

可以看出,服务器其实也是使用了 东八区

😮 也就是基本可以排除如各种社区说的服务器时区设置问题!

脑洞时刻

考虑到方便进一步定位,我这边获取了 Grafana 对应图表查询的模板内容

select 
	$__timeGroupAlias(ufr.ct,$__interval),
	mf.name as '表单名',
	count(ufr.id) AS '提交量'
from user_form_request ufr 
left join manual_forms mf on ufr.form_type = mf.id 
WHERE
  $__timeFilter(ufr.ct)
GROUP BY  1,ufr.form_type 
ORDER BY $__timeGroup(ufr.ct,$__interval,0)

同时获取了该模板最近一次查询的 SQL

select 
UNIX_TIMESTAMP(ufr.ct) DIV 86400 * 86400 AS "time",
mf.name as '表单名',
count(ufr.id) AS '提交量'
from user_form_request ufr 
left join manual_forms mf on ufr.form_type = mf.id 
WHERE
  ufr.ct BETWEEN FROM_UNIXTIME(1681142400) AND FROM_UNIXTIME(1681228799)
GROUP BY  1,ufr.form_type 
ORDER BY UNIX_TIMESTAMP(ufr.ct) DIV 86400 * 86400

从查询条件 ufr.ct BETWEEN FROM_UNIXTIME(1681142400) AND FROM_UNIXTIME(1681228799) 可知:

当前查询的是 2023-04-11 00:00:002023-04-11 23:59:59 的数据;这个时间范围是符合预期的(因为是我手动设置的)!

下面我跟进上面的 SQL 获取到对应结果内容

from_unixtime 时间unix_timestamp 时间表单名提交量
2023-04-10 08:00:001681084800封禁申诉1
2023-04-10 08:00:001681084800模拟器申请1
2023-04-10 08:00:001681084800充值异常2
2023-04-10 08:00:001681084800注销账号1
2023-04-10 08:00:001681084800找回账号1
2023-04-10 08:00:001681084800异常反馈10
2023-04-10 08:00:001681084800游戏建议2
2023-04-11 08:00:001681171200违规举报34
2023-04-11 08:00:001681171200注销账号3
2023-04-11 08:00:001681171200充值异常3
2023-04-11 08:00:001681171200找回账号26
2023-04-11 08:00:001681171200封禁申诉10
2023-04-11 08:00:001681171200游戏下载4
2023-04-11 08:00:001681171200模拟器申请20
2023-04-11 08:00:001681171200游戏建议8
2023-04-11 08:00:001681171200流水查询2
2023-04-11 08:00:001681171200异常反馈33

⁉️ 是不是瞬间来疑问了:为何时间格式化会出现 4月10日 数据

茅塞顿开

回归之前说的 GrafanaMySQL 时差偏移 8h 的问题,再结合上面的数据和 SQL,我们是不是有足够的资本来怀疑 UNIX_TIMESTAMP(xxx) 的机制导致了这个问题呢?

让我们来看看 官网关于 unix_timestamp 的说明

If UNIX_TIMESTAMP() is called with a date argument, it returns the value of the argument as seconds since ‘1970-01-01 00:00:00’ UTC. The server interprets date as a value in the session time zone and converts it to an internal Unix timestamp value in UTC.

也就是说 UNIX_TIMESTAMP() 会把我们的时间(此处假设是 2023-04-11 07:00:00)转成对应的 UTC 时间,而我们当前的服务器使用的是 东八区,所以转成 UTC 时间的时候就会减去 8h,即变成 UTC 时间 2023-04-10 23:00:00

然后结合上面 SQL 来代入 UNIX_TIMESTAMP('2023-04-11 07:00:00') DIV 86400 * 86400,本身是要取当天的零点(即 2023-04-11 00:00:00),最后因为被转成 UTC 2023-04-10 23:00:00,最后获得的是 2023-04-10 00:00:00

而如果此时使用 FROM_UNIXTIME(UNIX_TIMESTAMP('2023-04-11 07:00:00') DIV 86400 * 86400),因为 MySQL 会根据本身的时区进行优化可阅读性,会格式成 东八区 时间,所以在 2023-04-10 00:00:00 的基础上加上 8h,造就了前面数据表看到的 2023-04-10 08:00:00

解决方案

既然 UNIX_TIMESTAMP() 会默认帮我们减 8h,那我们只要默认给时间加 8h 再进行处理不就行了吗,下面是改造后的 Grafana 查询模板:

select
  $__timeGroupAlias(tmp.my_time,$__interval),
  tmp.name as '表单名',
  count(tmp.id) AS '提交量'
from (
  select 
  CONVERT_TZ(ufr.ct, '+00:00', '+08:00') as my_time,
  mf.name as name,
  ufr.id
  from user_form_request ufr 
  left join manual_forms mf on ufr.form_type = mf.id 
  WHERE
  $__timeFilter(ufr.ct)
) tmp
group by 1,tmp.name
ORDER BY $__timeGroup(tmp.my_time,$__interval,0)

至此,问题圆满解决,希望本次经验能为其他小伙伴也带来一些帮助!

有其他想法或者需要帮助的小伙伴欢迎在评论区一起交流!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要在Grafana中监控MySQL,您可以按照以下步骤操作: 1. 安装和配置Grafana:首先,您需要按照Grafana的官方文档安装和配置Grafana。您可以根据您的操作系统选择适当的安装方式。 2. 连接MySQL数据库:在Grafana中监控MySQL,您需要将MySQL数据库添加为数据源。在Grafana的管理界面中,选择“Configuration” -> “Data Sources”,然后点击“Add data source”。选择MySQL作为数据源类型,并填写相关的连接信息,如主机名、端口号、用户名和密码等。 3. 创建监控面板:在Grafana中创建监控面板来展示MySQL的指标数据。您可以使用Grafana提供的各种可视化工具来创建自定义的监控图表。选择“Create” -> “Dashboard”,然后点击“Add panel”来添加监控面板。在面板设置中,选择适当的数据源和查询语句来获取MySQL的指标数据,并选择适当的图表类型进行展示。 4. 配置告警规则:除了监控MySQL的指标数据,您还可以配置告警规则来及时通知您任何异常情况。在Grafana的管理界面中,选择“Alerting” -> “Notification channels”来配置告警通知方式,如电子邮件、Slack等。然后,在监控面板设置中,选择“Alert” -> “Create alert”来配置告警规则,如设置阈值、触发条件等。 通过以上步骤,您就可以在Grafana中监控MySQL并创建自定义的监控面板和告警规则了。请注意,具体的配置细节可能会因GrafanaMySQL的版本而有所不同,建议参考官方文档或在线资源进行详细配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不认输的猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值