反向链接
- [[00.Hexo 快速建站]]
- [[01.初识_Maven]]
- [[02.巧用Nexus搭建Maven私服]]
- [[11.OSS_Minio]]
- [[60.GitLab_CICD]]
- [[66.RustDesk]]
最近项目需要前端实现一个实时图表功能。
最开始的设计是让前端通过 Ajax 轮询的方式去调用接口获取数据库的数据,但考虑到其比较消耗资源,现在改用 WebSocket 技术实现。
实时图表的核心是相关数据变化就更新,那么后端该如何检测数据的变化呢?
其中之一的解决方案就是:在 MySQL 中使用触发器。
在 MySQL 的相关表中创建触发器后,当表中有数据插入、删除、更新时该触发器就去调用 Java 接口,而该接口被调用后就会去通知 WebSocket 的服务端去通知所有连接的客户端(前端)更新数据。
那么问题来了,要让触发器去调用一个 Java 接口,肯定需要发起 HTTP 请求,可 MySQL 触发器本身并不支持该功能,那么该如何发起 HTTP 请求呢?
答案是使用 MySQL-UDF-HTTP !
两者均为时间类型字段,格式都一致,主要有以下四点区别:
基于前面的分析:
长久以来,MySQL 数据库里的时间戳都是用的 int(10) unsigned 类型,后来看了些别人的代码,发现用 timestamp 好像也蛮不错的。
MySQL的 timestamp 类型内部其实本质是用的一个 int 整数来存储的从自 UTC 1970 年 1 月 1 日至今的秒数,所以无论是索引性能还是存储空间都没什么区别,MySQL 文档也有说明,当使用select from _unixtime(timestamp)
时,是直接访问的内部秒数,而不是格式化后再反格式化。
尽管大体一样,而 timestamp 类型带来了两点明显的好处:
SELECT
出来的结果直接就是可理解的CURRENT_TIMESTAMP
函数来设置默认值对于js代码中,new Date(timestamp * 1000)这种乘以1000的写法,总是让人遗忘,而数据库返回的结果直接就是格式化好的,js就只需要做截断或者字符替换操作,不容易出错得多。
于是我将系统全更换成 timestamp 类型了,然而好景不长,我又全折腾回int unsigned了,因为面对它所带来的两大坏处,它带来的两点好处显得微不足道了:
默认情况下 MySQL 的时区变量取值为 SYSTEM,即跟随服务器系统的时区:
1 | select @@time_zone; |
这意味着每次SELECT
的数据,都需要查询一下系统的时区设置,然后进行格式化,据说查询的过程还要获取全局锁,这就不仅有 CPU 的计算耗时问题,还会有阻塞问题。有建议的做法是设置@time_zone='+8'
来避免频繁对系统时区的查询,但很显然,在布署新环境时,有可能会忘记这件事。
时区问题,我想了好久,也无法绕过去。
中国时区是 CST,也就是 UTC+8(GMT+8),若应用只针对中国用户,那使用 CST 时区没有问题,但是若跨了时区,就必须存储 UTC 时间,然后各个客户端拿到这一绝对时间秒数后再转换成当地时区所对应的时间,特别像是美国及很多国家,不仅有时区问题,还有夏令时问题,这就更要依靠客户端的时区设置了。
其实 timestamp 内部的 int 也是使用的 UTC 绝对秒数,但是在SELECT
的时候,会转换成服务器所在时区的时间,这时问题就麻烦了,客户端拿到时间之后,正确的做法是先按服务器所在时区反格式化为绝对秒数,再根据当前时区设置格式化对应时间,这显然非常麻烦。
如果涉及到时区问题,最好的方案就是统一 UTC ,展示转换时区即可,即
可以认为 GMT 和 UTC 相等。