FlinkCDC同步PG数据到Opensearch时间精度丢失问题

260 阅读2分钟

一、背景

最近接到一个新需求需要加一timestamp类型的字段时间需要精确到毫秒的第三位,由于是使用FlnkCDC的方式将数据同步到opensearch。在接到需求之后很快将FlinkSQL修改完了,新加的字段值正常同步到opensearch.在测试过程中发现任务异常报错。

二、现象

报错如下图所示:

image.png 刚看到这个报错以为是数据库写入的时间格式有问题导致任务异常,去检查数据库的时候发现数据库中的数据是2023-11-20 02:00:26.230 一看不对咋少了一个零

三、解决方法

  1. 不要使用yyyy-mm-dd HH:mm:ss.SSS的时间format格式,使用时间格式yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
  2. 将FlinkSQL中对应时间字段类型由原来的timestamp修改为String
  3. 将source的时间格式format为String让opensearch自己去推断
  4. 直接上代码时间精度会丢失的代码
CREATE TABLE source_table (
    id BIGINT,
    name STRING,
    create_date TIMESTAMP,
    update_date TIMESTAMP,
    PRIMARY KEY (id) NOT ENFORCED
) WITH (
     'connector' = 'postgres-cdc',
     'hostname' = ,
     'port' = '5432',
     'username' = ,
     'password' = ,
     'decoding.plugin.name' = 'pgoutput',
     'debezium.slot.name' = ,
     'database-name' = ,
     'schema-name' = ,
     'table-name' = 
)

CREATE TABLE sink_table(
    id BIGINT,
    name STRING,
    createDate TIMESTAMP,
    updateDate TIMESTAMP,
    PRIMARY KEY (id) NOT ENFORCED 
) WITH (
    'connector' = 'CustomerElasticsearch7Sink',
    'hosts' = ,
    'username' = ,
    'password' = ,
    'index' = 
)

INSERT INTO sink_table SELECT * from source_table
  1. 修改之后时间精度不会丢失的代码
CREATE TABLE source_table (
    id BIGINT,
    name STRING,
    create_date TIMESTAMP,
    update_date TIMESTAMP,
    PRIMARY KEY (id) NOT ENFORCED
) WITH (
     'connector' = 'postgres-cdc',
     'hostname' = ,
     'port' = '5432',
     'username' = ,
     'password' = ,
     'decoding.plugin.name' = 'pgoutput',
     'debezium.slot.name' = ,
     'database-name' = ,
     'schema-name' = ,
     'table-name' = 
)

CREATE TABLE sink_table(
    id BIGINT,
    name STRING,
    createDate STRING,
    updateDate STRING,
    PRIMARY KEY (id) NOT ENFORCED 
) WITH (
    'connector' = 'CustomerElasticsearch7Sink',
    'hosts' = ,
    'username' = ,
    'password' = ,
    'index' = 
)

INSERT INTO sink_table 
SELECT 
    id,
    name,
    date_format(timestampadd(HOUR, -0, create_date),'yyyy-MM-dd''T''HH:mm:ss.SSS''Z'''),
    date_format(timestampadd(HOUR, -0, update_date),'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''')
from source_table

四、原因分析

www.elastic.co/guide/en/el… discuss.elastic.co/t/formatted…