prestosql(trino) hive时间戳显示不正确排查

TLDR: 服务器的时区设置有问题。


prestosql也老早改名trino了…
公司的数仓很早就建了且没有升级,所以版本很老。
hive使用的是1.1版本,对应的ORC版本是0.12。
装了一个远古版本的prestodb,后来在2019年又装了一个prestosql

讲完了背景说一下问题。
hive中有timestamp字段的表,在hiveprestodb中显示正常,比如2022-02-19 08:00:00,但是在prestosql中显示的是2022-02-19 16:00:00,也就是多了8H。
最开始排查,检查hive,prestosqlprestodb的当前时间和时区,都显示为正常。排除物理机时区不同或者设置了不同时区。

既然数据库设置没问题,那看一下ORC,dump了一下元信息,发现对应字段类型是timestamp,dump一下数据,发现存储的是2022-02-19 08:00:00
???
存的是2022-02-19 08:00:00?看ORC的类型可知时间戳分类两个类型,一个是UTC一个是with timezone offset的,stripe信息中没有timezone信息,为什么timestamp存的是东八区的时间,而不是UTC?

看到这个渐渐有点明朗,东八区的时间的确是2022-02-19 08:00:00,但时间戳存的也是2022-02-19 08:00:00,那也就是hiveprestodb直接把这个当作东八区来用了所以正常显示,而prestosql是认为2022-02-19 08:00:00是UTC时间,所以查询显示的时候自动加了当前时区的8小时。

再检查了一下使用的ORC版本,发现版本很低,对比release信息,这个版本是不支持timezone offset的。
找到定义文档,发现一段话:

Before ORC-135, the local timezone offset was included and they were stored as minimum and maximum. After ORC-135, the timestamp is adjusted to UTC before being converted to milliseconds and stored in minimumUtc and maximumUtc.
emmm,所以他存的timestamp实际上是包括了本地时间偏移。

再加上hiveprestodb用的版本过低,读取timestamp的时候用的就是当前时区。所以显示没问题。
prestosql版本更新,且支持ORC的timestamp with timezone offset,那如果stripe里没有时区会怎么样呢,我们使用的版本看起来是会默认把timestamp当作UTC
.(见后面分析)

经过上面一顿分析,参考trino的文档找到了一个参数hive.orc.time-zone,实测无效因为这个是341版本实装的,版本过低。
在看了一眼老版本要用参数hive.time-zone,设置回Asia/Shanghai后回复正常了。


本来以为事情就这么解决。
但后来一想这个trino升级应该不会这么不谨慎吧,如果有这个问题那应该大面积爆发且爆栈,issue很多才对。
实际上这个资料都很难搜到。
那可不可能是自己的问题呢。

再次对比prestodbpresosql,他们现在配置的区别就是prestosql设置了time-zone。
这个参数很早就支持了,那为什么prestodb不设置也可以呢。
查了下这个参数的默认值用的是JVM Default
emmm, 那主要就是两个user.timezone这个属性。
jcmd pid VM.system_properties检查了一下… …
果然,prestosql写的是user.timezone=UTC,而prestodb的是user.timezone=Asia/Shanghai
破案… …
这个属性一般不用自己设置,看了下服务器,emmm,部署prestosql的用的是UTC,所以他把hive.time-zone设置为了UTC,读取ORC也错了。

哎,走了一些弯路还在怀疑版本更新之后的一些兼容性问题。
不过也是必要的,最后发现是环境问题也是因为知道了对应的参数和其默认值。
排查问题最主要的还是要尽量刨根究底,不然会有错误的认知和结论。
哎,还是太菜了 …( _ _)ノ|。

参考资料

ORC Specification v1
Trino Release 341(8 Sep 2020)
How to set a JVM TimeZone Properly