暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OceanBase1.0时区功能介绍

  • 时区(Time Zone)

  地球是自西向东自转,东边比西边先看到太阳,东边的时间也比西边的早。东边时刻与西边时刻的差值不仅要以时计,而且还要以分和秒来计算,这给人们带来不便。为了克服时间上的混乱,1884年在华盛顿召开的一次国际经度会议,规定将全球划分为24个时区,并且英国(格林尼治天文台旧址)为本初子午线,即零度经线。

  • 国际协调时间(UTC)

  UTC是最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间。时区则是根据与UTC的偏差来定义自己的时间,例如中国在东八区,所以我们使用的时间是UTC + 8的结果。

时区的影响

  OceanBase中的时区功能尽可能与MySQL保持兼容,而对于MySQL表现不够合理的地方我们则进行了改进。时区主要影响的以下两点内容:

  • 时间相关函数

  当设置不同的时区信息时,一些时间相关函数的结果会根据时区的变化而变化。由下面的例子可见,当时区发生变化时now()和current_time()均受其影响。

OceanBase (root@oceanbase)> set time_zone='Asia/Shanghai';
Query OK, 0 rows affected (0.01 sec)OceanBase (root@oceanbase)> select utc_timestamp(), now(), current_time();
+---------------------+---------------------+----------------+| utc_timestamp()     | now()               | current_time() |
+---------------------+---------------------+----------------+| 2017-01-18 12:02:40 | 2017-01-18 20:02:40 | 20:02:40       |
+---------------------+---------------------+----------------+1 row in set (0.01 sec)

OceanBase (root@oceanbase)> set time_zone='America/Adak';
Query OK, 0 rows affected (0.01 sec)OceanBase (root@oceanbase)> select utc_timestamp(), now(), current_time();
+---------------------+---------------------+----------------+| utc_timestamp()     | now()               | current_time() |
+---------------------+---------------------+----------------+| 2017-01-18 12:04:34 | 2017-01-18 02:04:34 | 02:04:34       |
+---------------------+---------------------+----------------+
  • TIMESTAMP类型的列

  TIMESTAMP类型的值会根据当前的时区转换为UTC时间进行存储,在读取时又UTC值转换为当前时区时间。例如,对于同一份数据,指定不同的时区,查询结果不同。

OceanBase (root@oceanbase)> set @@session.time_zone="Asia/Shanghai";
Query OK, 0 rows affected (0.01 sec)OceanBase (root@oceanbase)> insert into t1 values("2017-01-01 00:00:00");
Query OK, 1 row affected (0.00 sec)OceanBase (root@oceanbase)> select * from t1;
+---------------------+| c1                  |
+---------------------+| 2017-01-01 00:00:00 |
+---------------------+1 row in set (0.00 sec)

OceanBase (root@oceanbase)> set @@session.time_zone='US/Eastern';
Query OK, 0 rows affected (0.00 sec)OceanBase (root@oceanbase)> select * from t1;
+---------------------+| c1                  |
+---------------------+| 2016-12-31 11:00:00 |
+---------------------+1 row in set (0.01 sec)

时区的导入与更新

  • 导入

  OceanBase将时区信息保存在系统表中。当需要导入时区信息是,我们根据操作系统的时区文件生成INSERT语句,将时区信息插入到这三张表中。

  • 更新

  上述操作仅仅是将时区信息导入系统表中,我们需要执行ALTER SYSTEM REFRESH TIME_ZONE_INFO命令来通知整个集群的所有SERVER更新本地时区信息的缓存,当有新的QUERY到来时则可以使用新的时区信息进行处理。而MySQL中在导入时区信息后,要求重启server才能够将缓存的旧值更新掉。

时区的设置

  通过设置TIME_ZONE系统变量可以指定当前SESSION或系统的时区,OceanBase当前支持两种设置格式。

1.指定一个合法的偏移,例如:分别指定SESSION和系统时区偏移为'+8:00'。

OceanBase (root@oceanbase)> set @@session.time_zone='+8:00';Query OK, 0 rows affected (0.01 sec)

OceanBase (root@oceanbase)> set @@global.time_zone='+8:00';Query OK, 0 rows affected (0.02 sec)

2.指定一个合法的时区名称,例如:分别指定SESSION和系统时区为'Asia/Shanghai'。

OceanBase (root@oceanbase)> set @@session.time_zone='Asia/Shanghai';Query OK, 0 rows affected (0.01 sec)

OceanBase (root@oceanbase)> set @@global.time_zone='Asia/Shanghai';Query OK, 0 rows affected (0.02 sec)

夏令时

  • 概念

  夏令时是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮较早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。

  • 问题

  由于夏令时的存在,可能会带来下面的两个问题:

  1. 当前时区由非夏令时转换到夏令时后,有一段时间会“消失”。例如,US-Pacific时区,在进入夏令时后,当地时间由1:59am直接变为3:00am,这时对于当前时区有一个小时“消失”了。

  2. 当前时区由夏令时转换到非下令时后,有一段时间会“重叠”。例如,US-Pacific时区,当从夏令时退出时,当地时间由1:59am直接变为1:00am,因此有一个小时”重叠“了。

  • 处理

  由上面的叙述可知,向timestamp列插入的数据会转换为UTC值进行存储,而由于夏令时的存在则会导致上面两种不明确的行为(注:其他LOCAL TIME 向UTC的转换同样存在这样的问题)。如果插入的时间正好落在“消失”的时间片范围,应该如何向UTC转换;如果插入的时间正好落在"重叠"的时间片,又应该选择哪个offset(夏令时或非夏令时)计算UTC值。

MySQL处理方法

  MySQL处理“消失”时间值时(将其转换为UTC值),如果转换发生在CONVERT_TZ函数中,会按照一定规则选择一个默认值,并不受SQL MODE影响;如果转换发生在INSERT语句中,则进一步区分当前是否为严格模式,如果是则报错,否则插入一个默认值。

  对于“重叠”时间,无论在何种上下文向UTC转换均会转换成功,其值为按照一定规则计算的默认值。

OceanBase处理方法

  对于MySQL的表现我们认为对用户不够友好,因此并没有与其保持兼容。当用户向timestamp列插入一个在"消失"时间片范围内的时间值时,我们直接报错。因为这个时间值在当前时区是不合法的,插入这样的值是不合理的。

  对于“重叠”的情况,我们采用两种手段进行处理:

  1. 允许时间值中同时指定时区信息和夏令时信息。例如:'1999-10-29 01:30:00 US/Pacific PDT'表示该使用US/Pacific时区,且为夏令时时间,这样就可以消除"重叠"时间是否为夏令时的歧义了。

  2. 通过ERROR_ON_OVERLAP_TIME系统变量控制发生歧义时的行为。该值为TRUE时,如果插入的“重叠”时间值没有指定夏令时信息,直接报错;如果该系统变量为FALSE,“重叠”时间会默认按照标准时间(非夏令时)进行处理。

总结

  时区功能实现过程中我们同时参考了MySQL(例如:时区信息的导入)和Oracle的行为(例如:夏令时的处理),我们的最终目标是为用户提供一个准确、一致和友好的功能。该功能为OceanBase支持国际业务提供了保障,也为OceanBase的开疆扩土做了准备,OceanBase的功能也将会越加的丰富,敬请期待。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论