【发布时间】:2020-05-06 18:03:22
【问题描述】:
在 Postgres 10.10 数据库中,我有一个表 table1 和 AFTER INSERT 上的 table1 触发器 table2:
CREATE TABLE table1 (
id SERIAL PRIMARY KEY,
-- other cols
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
CREATE UNIQUE INDEX table1_pkey ON table1(id int4_ops);
CREATE TABLE table2 (
id SERIAL PRIMARY KEY,
table1_id integer NOT NULL REFERENCES table1(id) ON UPDATE CASCADE,
-- other cols (not used in query)
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
CREATE UNIQUE INDEX table2_pkey ON table2(id int4_ops);
此查询在应用程序启动时执行:
CREATE OR REPLACE FUNCTION after_insert_table1()
RETURNS trigger AS
$$
BEGIN
INSERT INTO table2 (table1_id, ..., created_at, updated_at)
VALUES (NEW.id, ..., 'now', 'now');
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';
DROP TRIGGER IF EXISTS after_insert_table1 ON "table1";
CREATE TRIGGER after_insert_table1
AFTER INSERT ON "table1"
FOR EACH ROW
EXECUTE PROCEDURE after_insert_table1();
我注意到table2 上的一些created_at 和updated_at 值与table1 不同。事实上,table2 的值大多较旧。
这里有 10 个连续的条目,它们显示了在几分钟内的巨大差异:
|table1_id|table1_created |table2_created |diff |
|---------|--------------------------|-----------------------------|----------------|
|2000 |2019-11-07 22:29:47.245+00|2019-11-07 19:51:09.727021+00|-02:38:37.517979|
|2001 |2019-11-07 22:30:02.256+00|2019-11-07 13:18:29.45962+00 |-09:11:32.79638 |
|2002 |2019-11-07 22:30:43.021+00|2019-11-07 13:44:12.099577+00|-08:46:30.921423|
|2003 |2019-11-07 22:31:00.794+00|2019-11-07 19:51:09.727021+00|-02:39:51.066979|
|2004 |2019-11-07 22:31:11.315+00|2019-11-07 13:18:29.45962+00 |-09:12:41.85538 |
|2005 |2019-11-07 22:31:27.234+00|2019-11-07 13:44:12.099577+00|-08:47:15.134423|
|2006 |2019-11-07 22:31:47.436+00|2019-11-07 13:18:29.45962+00 |-09:13:17.97638 |
|2007 |2019-11-07 22:33:19.484+00|2019-11-07 17:22:48.129063+00|-05:10:31.354937|
|2008 |2019-11-07 22:33:51.607+00|2019-11-07 19:51:09.727021+00|-02:42:41.879979|
|2009 |2019-11-07 22:34:28.786+00|2019-11-07 13:18:29.45962+00 |-09:15:59.32638 |
|2010 |2019-11-07 22:36:50.242+00|2019-11-07 13:18:29.45962+00 |-09:18:20.78238 |
连续的条目在序列中具有相似的差异(大部分为负数/大部分为正数)和相似的数量级(大部分为分钟与大部分为小时),但也有例外
以下是前 5 个最大的积极差异:
|table1_id|table1_created |table2_created |diff |
|---------|--------------------------|-----------------------------|----------------|
|1630 |2019-10-25 21:12:14.971+00|2019-10-26 00:52:09.376+00 |03:39:54.405 |
|950 |2019-09-16 12:36:07.185+00|2019-09-16 14:07:35.504+00 |01:31:28.319 |
|1677 |2019-10-26 22:19:12.087+00|2019-10-26 23:38:34.102+00 |01:19:22.015 |
|58 |2018-12-08 20:11:20.306+00|2018-12-08 21:06:42.246+00 |00:55:21.94 |
|171 |2018-12-17 22:24:57.691+00|2018-12-17 23:16:05.992+00 |00:51:08.301 |
以下是前 5 个最大的负面差异:
|table1_id|table1_created |table2_created |diff |
|---------|--------------------------|-----------------------------|----------------|
|1427 |2019-10-15 16:03:43.641+00|2019-10-14 17:59:41.57749+00 |-22:04:02.06351 |
|1426 |2019-10-15 13:26:07.314+00|2019-10-14 18:00:50.930513+00|-19:25:16.383487|
|1424 |2019-10-15 13:13:44.092+00|2019-10-14 18:00:50.930513+00|-19:12:53.161487|
|4416 |2020-01-11 00:15:03.751+00|2020-01-10 08:43:19.668399+00|-15:31:44.082601|
|4420 |2020-01-11 01:58:32.541+00|2020-01-10 11:04:19.288023+00|-14:54:13.252977|
负面差异比正面差异多 10 倍。数据库时区为 UTC。
table2.table1_id 是外键,所以在table1 上的插入完成之前应该是不可能插入的。
table1.created_at 由 Sequelize 设置,使用模型上的选项 timestamps: true。
将一行插入table1 时,它是在事务中完成的。从我能找到的文档中,触发器是在同一个事务中执行的,所以我想不出原因。
我可以通过将触发器更改为使用NEW.created_at 而不是“现在”来解决此问题,但我很好奇是否有人知道此错误的原因是什么?
这是用于生成上述差异表的查询:
SELECT
table1.id AS table1_id,
table1.created_at AS table1_created,
table2.created_at AS table2_created,
(table2.created_at - table1.created_at) AS diff
FROM table1
INNER JOIN table2 ON
table2.table1_id = table1.id AND (
(table2.created_at - table1.created_at) > '2 min' OR
(table1.created_at - table2.created_at) > '2 min')
ORDER BY diff;
【问题讨论】:
-
'now' 不是时间戳,它是一个字符串。尝试使用 now() 函数。但是对于您的直接问题,您可以 new.created_at 从 table1 行。
-
它们是相同的:
SELECT 'now'::timestamp = now();。知道我可以使用NEW.created_at,正在询问其根本原因 -
1.您确定这两个表都没有收到更新吗?您可以通过查看
xmax来识别插入的行。请参阅:stackoverflow.com/a/40880200/939860 2. 表table1上是否还有其他可能干扰的触发器? 3、你的INSERT的目标列列表和VALUES列表的元素个数一样吗? -
一般情况下,请逐字显示完整的触发器和触发器函数定义,并始终显示您的 Postgres 版本。此外,错误可能出现在用于连接
table1和table2以检查差异的查询中。我们真的需要查看查询和表定义。总而言之,这是一个水晶球的案例...... -
@ErwinBrandstetter 我已经在上面添加了要求的详细信息
标签: postgresql transactions timestamp sequelize.js plpgsql