为何node-pg中UPDATE无法设置更晚的ended_at时间?
问题分析:ended_at时间与事务开始时间一致的原因
问题场景
使用node-pg执行以下PL/pgSQL脚本:
await db.query( `DO $$ DECLARE pbid INT; BEGIN INSERT INTO public.bp(process_id) SELECT ${ID} RETURNING id INTO pbid; COMMIT; REFRESH MATERIALIZED VIEW public.vm WITH DATA; UPDATE public.bp SET under_process = FALSE, ended_at = now() WHERE id = pbid; END;$$;` );
脚本执行正常,但ended_at字段始终等于事务开始时间,而物化视图刷新过程耗时约2分钟,且已禁用会设置new.ended_at := now()的触发器。
核心原因
PostgreSQL中now()(包括CURRENT_TIMESTAMP)函数的返回值是事务启动时的时间戳,在整个事务执行周期内保持固定不变,不会随实际时间推移更新。
尽管脚本中显式写了COMMIT,但标准PL/pgSQL的DO块默认作为单个事务执行(若你的环境未因显式COMMIT报错,可能是特殊配置,但不影响时间戳逻辑)。UPDATE语句中的now()调用,本质上还是使用事务启动时的时间,因此即使中间物化视图刷新耗时2分钟,ended_at依然和事务开始时间一致。
解决方案
若需要记录UPDATE语句实际执行时的时间,应使用clock_timestamp()函数——它会返回当前的实际系统时间,而非事务启动时间。修改后的UPDATE语句如下:
UPDATE public.bp SET under_process = FALSE, ended_at = clock_timestamp() WHERE id = pbid;
内容的提问来源于stack exchange,提问作者user1889017
相关产品推荐
相关产品推荐

