我的想法是实现一个基本的“矢量时钟”,其中时间戳是基于时钟的,总是前进并保证是唯一的。如何在PostgreSQL中生成唯一的时间戳?
例如,在一个简单的表:
CREATE TABLE IF NOT EXISTS timestamps (
last_modified TIMESTAMP UNIQUE
);
我使用触发器来设置插入之前的时间戳值。它基本上只是去到未来,当两个刀片在同一时间到达:
CREATE OR REPLACE FUNCTION bump_timestamp()
RETURNS trigger AS $$
DECLARE
previous TIMESTAMP;
current TIMESTAMP;
BEGIN
previous := NULL;
SELECT last_modified INTO previous
FROM timestamps
ORDER BY last_modified DESC LIMIT 1;
current := clock_timestamp();
IF previous IS NOT NULL AND previous >= current THEN
current := previous + INTERVAL '1 milliseconds';
END IF;
NEW.last_modified := current;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS tgr_timestamps_last_modified ON timestamps;
CREATE TRIGGER tgr_timestamps_last_modified
BEFORE INSERT OR UPDATE ON timestamps
FOR EACH ROW EXECUTE PROCEDURE bump_timestamp();
然后我在两个单独的客户端运行插入了大量的:
DO
$$
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO timestamps DEFAULT VALUES;
END LOOP;
END;
$$;
正如预期的那样,我得到的冲突:
ERROR: duplicate key value violates unique constraint "timestamps_last_modified_key"
État SQL :23505
Détail :Key (last_modified)=(2016-01-15 18:35:22.550367) already exists.
Contexte : SQL statement "INSERT INTO timestamps DEFAULT VALUES"
PL/pgSQL function inline_code_block line 4 at SQL statement
@rach suggested与一个SEQUENCE
对象混合current_clock()
,但它可能意味着摆脱的类型。即使我真的不知道如何解决隔离问题...
有没有一种常见的模式来避免这种情况?
感谢您的见解:)
出了什么问题只是一个序列?你真的需要时间吗?在2列(时间戳,序列)上使用密钥怎么办?否则你有V1 UUID。 – jcaron
为什么不使用'now()'? 'INSERT INTO timestamps now();'或者将该字段的默认值设置为now(),最终不能插入重复的now()值,因为它随每个事务而改变。 – Solrac
@SolracRagnarockradio,同一事务中的任何多次插入都会得到相同的时间戳。也不确定时间戳的微秒准确性会保证不同的值。 – jcaron