PostgreSQL pg_backup_start_time() CST 时区转换 问题

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介:

PostgreSQL的物理备份方法之一 :
在使用pg_start_backup()函数新建备份点后,用户可以开始拷贝PG的数据文件。

postgres=# select pg_start_backup('a'),now();
 pg_start_backup |              now              
-----------------+-------------------------------
 0/50000028      | 2016-05-06 11:03:30.917509+08
(1 row)

调用pg_start_backup后,会创建一个检查点,同时在$PGDATA中新建一个backup_label文件。
里面包含了START TIME的信息,是创建完检查点后的时间。

START WAL LOCATION: 0/50000028 (file 000000010000000000000014)
CHECKPOINT LOCATION: 0/50000028
BACKUP METHOD: pg_start_backup
BACKUP FROM: master
START TIME: 2016-05-06 11:03:33 CST
LABEL: a

但是,使用pg_backup_start_time得到的时间与之不符。

postgres=# select pg_backup_start_time();
  pg_backup_start_time  
------------------------
 2016-05-07 01:03:33+08
(1 row)

原因分析,首先我们要看看pg_backup_start_time的代码

postgres=# \df+ pg_backup_start_time
                                                                                         List of functions
   Schema   |         Name         |     Result data type     | Argument data types |  Type  | Security | Volatility |  Owner   | Language |     Source code      |          Description           
------------+----------------------+--------------------------+---------------------+--------+----------+------------+----------+----------+----------------------+--------------------------------
 pg_catalog | pg_backup_start_time | timestamp with time zone |                     | normal | invoker  | stable     | postgres | internal | pg_backup_start_time | start time of an online backup
(1 row)

代码如下

/*
 * Returns start time of an online exclusive backup.
 *
 * When there's no exclusive backup in progress, the function
 * returns NULL.
 */
Datum
pg_backup_start_time(PG_FUNCTION_ARGS)
{
        Datum           xtime;
        FILE       *lfp;
        char            fline[MAXPGPATH];
        char            backup_start_time[30];

        /*
         * See if label file is present
         */
        lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
        if (lfp == NULL)
        {
                if (errno != ENOENT)
                        ereport(ERROR,
                                        (errcode_for_file_access(),
                                         errmsg("could not read file \"%s\": %m",
                                                        BACKUP_LABEL_FILE)));
                PG_RETURN_NULL();
        }

        /*
         * Parse the file to find the START TIME line.
         */
        backup_start_time[0] = '\0';
        while (fgets(fline, sizeof(fline), lfp) != NULL)
        {
                if (sscanf(fline, "START TIME: %25[^\n]\n", backup_start_time) == 1)
                        break;
        }

        /* Check for a read error. */
        if (ferror(lfp))
                ereport(ERROR,
                                (errcode_for_file_access(),
                           errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE)));

        /* Close the backup label file. */
        if (FreeFile(lfp))
                ereport(ERROR,
                                (errcode_for_file_access(),
                          errmsg("could not close file \"%s\": %m", BACKUP_LABEL_FILE)));

        if (strlen(backup_start_time) == 0)
                ereport(ERROR,
                                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));

        /*
         * Convert the time string read from file to TimestampTz form.
         */
        xtime = DirectFunctionCall3(timestamptz_in,
                                                                CStringGetDatum(backup_start_time),
                                                                ObjectIdGetDatum(InvalidOid),
                                                                Int32GetDatum(-1));

        PG_RETURN_DATUM(xtime);
}

所以从代码可以看到pg_backup_start_time是从backup_label中获取到启动时间,并转化为带时区的时间的。

CST时间,CST同时可以代表如下 4 个不同的时区:

Central Standard Time (USA) UT-6:00
Central Standard Time (Australia) UT+9:30
China Standard Time UT+8:00
Cuba Standard Time UT-4:00

所以问题其实是出在时区转化这里:

postgres=# show timezone;
 TimeZone 
----------
 PRC
(1 row)

postgres=# select timestamp '2016-05-06 11:03:33 CST';
      timestamp      
---------------------
 2016-05-06 11:03:33
(1 row)

postgres=# select timestamptz '2016-05-06 11:03:33 CST';
      timestamptz       
------------------------
 2016-05-07 01:03:33+08
(1 row)

PostgreSQL pg_backup_start_time应该是把CST用USA时区来处理的

postgres=# set timezone='-6';
SET
postgres=# select pg_backup_start_time();
  pg_backup_start_time  
------------------------
 2016-05-06 11:03:33-06
(1 row)
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
关系型数据库 PostgreSQL
Postgresql设置时区
Postgresql设置时区
|
关系型数据库 数据库 PostgreSQL
postgresql 时区配置,系统主机与数据库时间不一致
--有时候操作系统的时间与pg的时间不一致,这往往时两者时区不一致造成的 --查看系统时间与时区 [postgres@rudy_01 data]$ date Thu Nov 19 09:3...
1611 0
|
关系型数据库 PostgreSQL 数据库
postgresql 时区与时间函数
--把时间戳转成epoch值 postgres=# select extract(epoch from now()); date_part ------------------ 1447898857.
998 0
|
关系型数据库 PostgreSQL 数据库
|
关系型数据库 分布式数据库 PolarDB
|
关系型数据库 分布式数据库 PolarDB
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
363 0
|
存储 缓存 关系型数据库
|
存储 SQL 并行计算
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍(中)
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍
419 0
|
存储 算法 安全
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍(下)
PolarDB for PostgreSQL 开源必读手册-开源PolarDB for PostgreSQL架构介绍
379 0
|
关系型数据库 分布式数据库 开发工具

相关产品

  • 云原生数据库 PolarDB