timestamp和timestamptz都占用8个字节,在存储时间时并没有本质的区别,都不携带时区信息。只是在insert保存数据和select给数据库客户端返回数据时处理方式不同。

下边以具体示例解释这两种数据类型的差别,以及他们与数据库链接时区(session对应的时区)和postgresql数据库时区之间的关系。下边例子使用的数据库时区是Etc/UTC (GMT + 0),首先创建表,然后做相应操作:

test_db=> CREATE TABLE test_table (id SERIAL NOT NULL PRIMARY KEY,lable TEXT NOT NULL,
timestamp_col TIMESTAMPTZ NOT NULL,timestamptz_col TIMESTAMPTZ NOT NULL);
CREATE TABLE
test_db=> insert into test_table(lable, timestamp_col, timestamptz_col) values ('haha',
'2022-04-13 01:15:55','2022-04-13 01:15:55');
INSERT 0 1
test_db=> select * from test_table;id | lable |    timestamp_col    |    timestamptz_col
----+-------+---------------------+------------------------1 | haha  | 2022-04-13 01:15:55 | 2022-04-13 01:15:55+00
(1 row)注:因为当前session时区和数据库时区都是Etc/UTC,所以数据库保存的时间,timestamp_col
和timestamptz_col都是一样的。select显示结果也是一样的。test_db=> show timezone;TimeZone
----------Etc/UTC
(1 row)test_db=> SET TIMEZONE='Asia/Shanghai';
SET
test_db=> show timezone;TimeZone
---------------Asia/Shanghai
(1 row)test_db=> insert into test_table(lable, timestamp_col, timestamptz_col) values ('hello','2022-04-13 01:15:55','2022-04-13 01:15:55');
INSERT 0 1
test_db=> select * from test_table;id | lable |    timestamp_col    |    timestamptz_col
----+-------+---------------------+------------------------1 | haha  | 2022-04-13 01:15:55 | 2022-04-13 09:15:55+082 | hello | 2022-04-13 01:15:55 | 2022-04-13 01:15:55+08
(2 rows)注:因为当前session时区是Asia/Shanghai, 而数据库时区都是Etc/UTC,所以数据库保存的时间,timesttamp_col保存
的时间是2022-04-13 01:15:55,而timestamptz_col保存的时间是2022-04-12 17:15:55。当执行selects时,timestamp
类型字段不做任何转换,而timestamptz类型的字段,需要转换成当前session对应的时区的时间,所以针对第二行看起来
timesttamp_col和timestamptz_col的结果还是一样的,而第一行,结果就不一样了。test_db=> SET TIMEZONE='Asia/Tokyo';
SET
test_db=> show timezone;TimeZone
------------Asia/Tokyo
(1 row)test_db=> select * from test_table;id | lable |    timestamp_col    |    timestamptz_col
----+-------+---------------------+------------------------1 | haha  | 2022-04-13 01:15:55 | 2022-04-13 10:15:55+092 | hello | 2022-04-13 01:15:55 | 2022-04-13 02:15:55+09
(2 rows)注:因为当前session时区是Asia/Tokyo(GMT+9), 而数据库时区都是Etc/UTC,当执行selects时,
timestamp类型字段不做任何转换,而timestamptz类型的字段,需要转换成当前session对应的时区的时间,
所以看起来timesttamp_col和timestamptz_col的结果还是一样的。

从上边的输出可以看出,随着数据库连接的时区的改变,同样的数据显示的不一样。对于timestamptz_col列,他会随着数据库链接session对应的时区的改变,而改变。而timestamp_col列,则不改变,只是把保存在数据库中的原始数据原封不动的返回给数据库链接客户端。

在插入(保存)数据时,不管是timestamp还是timestamptz,都不会保存时区信息,这也是为什么这两种类型的数据都占用8个字节,保存的时间精度也都是一样的。但是针对timestamp_col字段,只是把insert语句的时间原封不动的保存到数据库中,select的时候原封不动的返回,不会去考虑时区转换问题。而timestamptz, insert时会转换成数据库对应的时区的时间,select时,再转换成session对应的时区的时间。

因为上边我们设置的时区都是针对当前所在数据库链接的(所谓的session),当新建一个链接之后,我们之前对应之前链接设置的session信息就会丢失。

$ psql -h localhost -U test_user -p 6432 -d test_db;
Password for user test_user:
psql (14.2, server 14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.test_db=> select * from test_table;id | lable |    timestamp_col    |    timestamptz_col
----+-------+---------------------+------------------------1 | haha  | 2022-04-13 01:15:55 | 2022-04-13 01:15:55+002 | hello | 2022-04-13 01:15:55 | 2022-04-12 17:15:55+00
(2 rows)test_db=> show timezone;TimeZone
----------Etc/UTC
(1 row)

如上所示,新建一个链接之后,当前session所在的链接又变回了数据库的默认时区。

如果要修改数据库的时区,而非session的时区,则需要修改postgresql.conf文件,

Find postgresql.conf file.
# find / -name postgresql.conf/var/lib/pgsql/12/data/postgresql.conf
Change timezone in the postgresql.conf file
# vi /var/lib/pgsql/12/data/postgresql.conf...log_timezone = 'Asia/Shanghai'...timezone = 'Asia/Shanghai':wq

注意不同版本的postgresql,对应的配置文件路径可能不一样。修改完之后,需要重启。

总结:

1. timestamp和timestamptz类型的数据虽然都不保存时区信息,但是timestamptz却通过结合数据库设置的时区,session对应的时区以及timestamptz本身保存的数据,将正确的时间返回给客户端。也就是说从宏观上,timestamptz看起来确实像是保存了时区信息的timestamp数据,只不过这个时区是整个数据库设置的时区。

2. 什么时候使用timestamptz类型,什么时候使用timestamp?

简单说针对简单应用,只有单一客户端(单体应用)或同类型多个应用访问数据库(比如多个微服务),如果数据库保存的时间是由客户端应用程序保证时区正确性,这时就可以使用timestamp。因为这时,不管数据库的时区是Etc/UTC还是'Asia/Shanghai',数据库都不会对客户端传过来的数据做处理,只是原封不动的保存。select的时候再原封不动的返回。至于应用程序的客户端,比如一个新闻web应用的客户端是浏览器,如果希望根据浏览器所在区域的时区正确显示从数据库返回的时间,这是需要新闻web应用做转换,或者在时间上加上时区信息一起返回给浏览器客户端,由客户端做时间转换。

而如果有多种不类型客户端需要访问同一数据库,这个时候可以考虑使用timestamptz, 这样不管哪个客户端都可以根据当前session的时区正确获取对应的时间。

以上只是个人理解,可能有不准确的地方还望指正。

最后,需要说明的是,针对整个数据库的时区设置,个人认为作用不大。唯一的用处也许是使用postgresql命令行客户端psql连接数据库时,使session默认的时区设置成跟整个数据库时区一致,其他作用并不明显。因为如果你是使用例如DBeaver这种图形化数据库客户端工具,默认他会帮你把session的时区设置成DBeaver当前所在主机的时区,这样他显示timestamptz类型的数据时,也是完全没有问题的。

Postgresql 数据库时区(timezone)设置,以及TIMESTAMPTZ和TIMESTAMP数据类型的选择相关推荐

  1. Mysql查看数据库时区并设置时区

    使用IDEA连接数据库发生Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property ...

  2. 数据库建表时,对于字段的数据类型的选择

    本文是<数据库设计那些事>的笔记和思考. 有如下几种情形: 当字段可选择多个类型时(比如生日字段,可以用时间戳,即整数类型,可以用字符串 类型,也可以用日期 类型):整数.二进制 优于 日 ...

  3. postgresql设置postgres密码_django项目时配置postgresql数据库的方法

    python3.8使用pycharm在开发django项目时配置postgresql数据库的方法 django默认支持sqlite3,如果想使用最近最热门的关系型数据库postgresql时,那该怎么 ...

  4. Postgresql数据库设置开机自启动

    1.查找Postgresql数据库开机自启动脚本位置 [root@dragon ~]# find / -name start-scripts /opt/postgres/postgresql-9.4. ...

  5. PostgreSQL数据库设置登录数据库密码

    PostgreSQL数据库安装完以后会默认创建一个管理员的账号postgres用户,默认登录时是不需要密码验证就可以直接登录的 用命令行的sql语句来进行修改 登录到PostgreSQL数据库里 al ...

  6. flume系列之:hdfs.timeZone设置中国北京或上海时区

    flume系列之:hdfs.timeZone设置中国北京或上海时区 查看服务器时间 flume设置中国时区 查看服务器时间 date 2021年 12月 23日 星期四 10:09:49 CST hd ...

  7. 深度解析:Oracle数据库SYSDATE到PostgreSQL数据库最佳转换

    本文讨论了在Amazon RDS和Aurora 中使用PostgreSQL数据库时,与日期/时间相关的函数,并确定PostgreSQL数据库里的clock_timestamp()函数与Oracle中的 ...

  8. Debezium系列之:使用Debezium接入PostgreSQL数据库数据到Kafka集群的详细技术文档

    Debezium系列之:使用Debezium接入PostgreSQL数据库数据到Kafka集群的详细技术文档 一.概述 二.连接器的工作原理 1.安全 2.快照 3.Ad hoc snapshots ...

  9. 基于PostgreSQL的时区问题解决

    目录 ●实际业务场景中遇到的问题 ●时间戳(timestamp)定义 ●PostgreSQL时间日期类型 ●PostgreSQL时间戳使用的问题 ●解决方案一:变更字段类型 ●解决方案二:SQL层面 ...

最新文章

  1. 029 浏览器不能访问虚拟机的问题解决
  2. C#正则表达式提取HTML中IMG标签的SRC地址(转)
  3. 在CentOS7上配置SVN
  4. redis 后台运行_第一章 1.3Linux下安装Redis
  5. jMeter Thread group 对应的 constant timer
  6. H.264码流解析 一个SPS的nalu及获取视频的分辨率
  7. CF1245D Shichikuji and Power Grid
  8. tensorflow知识点
  9. 为什么索引不支持模糊查询_百度站长平台查询的关键词排名,为什么与实际不符合?...
  10. ocx控件 postmessage消息会消失_通过HackerOne漏洞报告学习PostMessage漏洞实战场景中的利用与绕过...
  11. tps是什么意思_系统了解精益生产系统TPS精益思想丛书介绍
  12. Linux服务器时间快8个小时,Linux系统时间快8小时解决方案
  13. 配置Android应用开发环境
  14. python数据分析numpy_Python数据分析之numpy学习(一)
  15. 通过高德地图获取 经纬度 以及地理位置等
  16. 炫酷好玩好用的卫星全景地图
  17. miui android系统 流量,[Android] 小米云流量最新魔改领100G流量教程
  18. 密码技术---分组密码的模式
  19. Java#21(抽象与接口)
  20. 大数据之flink定时器

热门文章

  1. 以瓴羊QuickBI为例,教你如何制作在线电子表格
  2. 有孚网络与NTT通信(中国)达成战略合作伙伴关系
  3. python实训报告5000字_Python程序设计实验报告(一)
  4. overflow 浏览器兼容问题
  5. 时间 Date 循环计时器
  6. 【每日一道智力题】之 赛马找最快
  7. 航空机票APP的设计与实现【AS开发+SQLITE】【附源码】
  8. java while打印_java – 值不会在while循环中更新,除非打印出来
  9. 信息安全系统设计基础学习项目_进程间通信
  10. 【自然语言处理】文本表示(一):One-Hot、BOW、TF-IDF、N-Gram