PostgreSQL触发器监控表数据落表时间是否有延迟

发布于:2023-10-25 ⋅ 阅读:(126) ⋅ 点赞:(0)


场景描述

  • 假如PostgreSQL数据库tzqdb下有tzq schema和tzq用户,下面有表tzq_log_t,表上开启了RLS行级策略,表数据是从上游拉取过来的数据,现在发现有丢失。现在要监控tzq_log_t的数据落表时间,看是上游的表的数据落表有延迟还是数据拉取工具的问题。

一、创建大账号(etl_tzq)监控普通账号(tzq)的表(tzq_log_t)数据。

用超管账号(prostgres、root等,此处用prostgres),在schema tzq下创建大账号(etl_tzq)监控普通账号(tzq)的表(tzq_log_t)数据。
让etl_tzq用户越过行级策略。
给etl_tzq用户授权scheme tzq的usage的权限。
给etl_tzq用户授权scheme tzq的create的权限。
给etl_tzq用户授权表tzq.tzq_log_t的trigger的权限。

CREATE USER etl_tzq WITH PASSWORD 'Tzq@123456';
alter user etl_mon_to_ins with bypassrls;
grant usage on schema tzq to etl_tzq;
grant create on schema tzq to etl_tzq;
grant trigger on tzq.tzq_log_t to etl_tzq;

二、创建监控数据表:tzq_monitor_data_t

用大账号(etl_tzq),创建监控数据表(tzq_monitor_data_t),监控业务表或者配置表(此处为上述的tzq_log_t表)的数据落表时间(creation_date)及更新时间(last_update_date)情况。
创建序列seq_tzq_monitor_data_t。
创建表tzq.tzq_monitor_data_t,主键id设置默认值为序列seq_tzq_monitor_data_t的下一个数值。

create sequence seq_tzq_monitor_data_t;
CREATE TABLE tzq.tzq_monitor_data_t (
  id int8 NOT NULL default nextval('seq_tzq_monitor_data_t'),
  table_name varchar(64),
  primary_id int8,
  log_number VARCHAR(100),
  source_creation_date TIMESTAMP(6),
  source_last_updated_date TIMESTAMP(6),
  operation varchar(100),
  creation_date TIMESTAMP(6) DEFAULT clock_timestamp(),
  PRIMARY KEY (id)
);
COMMENT ON TABLE  tzq.tzq_monitor_data_t IS '监控表数据表:监控表数据的落表时间是否有延迟,延迟多久';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.id IS '监控表数据表id:IT主键,系统自动生成';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.table_name IS '表名';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.primary_id IS '监控表的主键id';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.log_number IS '日志号';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.source_creation_date IS '原表创建时间';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.source_last_updated_date IS '原表更新时间';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.operation IS '操作:插入、更新、删除';
COMMENT ON COLUMN tzq.tzq_monitor_data_t.creation_date IS '实际落表时间';
ALTER TABLE tzq.tzq_monitor_data_t OWNER TO etl_tzq;

三、创建触发器函数:tzq_change_data_trigger()

用大账号(etl_tzq),创建触发器函数(tzq_change_data_trigger),对tzq_log_t表数据的落表情况记录到数据监控日志表(tzq_monitor_data_t)表里面。

CREATE or replace FUNCTION tzq_change_data_trigger()
  RETURNS trigger
  LANGUAGE 'plpgsql'
AS $$
    BEGIN
      IF TG_OP = 'INSERT' THEN
        INSERT INTO ins.tpc_monitor_data_t (table_name,primary_id,log_number,source_creation_date,source_last_updated_date,operation) values ('tzq_log_t',new.instruction_id,new.instruction_number,new.creation_date,new.last_update_date,'insert');
        RETURN NEW;
      ELSIF TG_OP = 'UPDATE'  THEN
        INSERT INTO ins.tpc_monitor_data_t (table_name,primary_id,log_number,source_creation_date,source_last_updated_date,operation) values ('tzq_log_t',new.instruction_id,new.instruction_number,new.creation_date,new.last_update_date,'update');
        RETURN NEW;
      ELSIF TG_OP = 'DELETE'  THEN
        INSERT INTO ins.tpc_monitor_data_t (table_name,primary_id,log_number,source_creation_date,source_last_updated_date,operation) values ('tzq_log_t',old.instruction_id,old.instruction_number,old.creation_date,old.last_update_date,'delete');
        RETURN OLD; --返回值要与ELSIF平齐,因为先插入后最好才执行返回
      END IF;
END;
$$;

四、创建触发器:tri_data_tzq_log_t,对表(tzq.tzq_log_t)的增删改进行监控

用大账号(etl_tzq),创建触发器(tri_data_tzq_log_t),对tzq.tzq_log_t表的增删改进行监控,执行函数tzq_change_data_trigger()

CREATE TRIGGER tri_data_tzq_log_t
  BEFORE INSERT OR UPDATE OR DELETE
  ON tzq.tzq_log_t
  FOR EACH ROW
EXECUTE PROCEDURE tzq_change_data_trigger();

五、给普通用户(tzq)授予监控日志表和序列的权限

  • 为了防止普通用户(tzq)修改或删除由大账号(etl_tzq)创建的表(tzq.tzq_monitor_data_t)的数据。
  • 在大账号(etl_tzq)下给用户(tzq)授权表(tzq.tzq_monitor_data_t)的select,insert权限。
  • 在大账号(etl_tzq)下给用户(tzq)授权序列(tzq.seq_tzq_monitor_data_t)的select,update权限。
-- 授权
grant select,insert on tzq.tzq_monitor_data_t to tzq;
grant select,update on ins.seq_tzq_monitor_data_t to tzq;

六、查源端最后更新时间和实际落表时间的相差秒数

查源端(表tzq_log_t)的最后更新时间(last_update_date)和实际落表时间(tzq.tzq_monitor_data_t.creation_date)的相差秒数。如果绝对值过大就说明有问题。

-- 查相差秒数
select to_number(
           date_trunc('second'
                     ,t.creation_date::TIMESTAMP - 
                      t.source_last_updated_date::TIMESTAMP)::text
       ,'9999999999999') as s1
      ,t.* 
  from tzq.tzq_monitor_data_t t
 where primary_id < 100000
   and operation = 'insert'
   -- and log_number = 'LOG2023102200000006'
 order by creation_date desc;

七、根据差异结果排查相关问题及总结

  • 这样,通过上面的一系列操作,我们就可以监控表(tzq_log_t)数据的落表时间跟实际落表时间的差异。
  • 如果差异过大(比如超过2分钟),我们就可以确定是上游的java代码落表时间有延迟。
  • 如果差异很小(5秒内),我们就可以确定是数据集成ETL工具漏数了。

至此,“PostgreSQL触发器监控表数据落表时间是否有延迟”的范例就演示完了,大家有不明白的地方可以给我留言,谢谢!


网站公告

今日签到

点亮在社区的每一天
去签到