我的想法是實現一個基本的「矢量時鐘」,其中時間戳是基於時鐘的,總是前進並保證是唯一的。如何在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