Генератор ID

Feb 21, 2017 21:05

В мультимастер-репликации базы данных возникает проблема одновременного появления одинаковых ID на разных узлах (если мы используем дефолтный простой автоинкремент).
Одно из решений - генерация ID случайным образом. В теории, конечно, на большой последовательности вероятность появления коллизии ID не нулевая, но для большинства задач - допустимая погрешность.
И, да, тип ИДшника надо заменить с дефолтного инта на bigint

Задать на таблице mytable новый генератор случайных ID:

ALTER TABLE mytable DROP CONSTRAINT mytable_pkey;
ALTER TABLE mytable ALTER COLUMN id DROP DEFAULT;
ALTER TABLE mytable ALTER COLUMN id TYPE bigint;
drop sequence mytable_id_seq;
create sequence mytable_id_seq;
CREATE OR REPLACE FUNCTION id_generator(OUT result bigint) AS $$
DECLARE
our_epoch bigint := 1314220021721;
seq_id bigint;
now_millis bigint;
-- the id of this DB shard, must be set for each
-- schema shard you have - you could pass this as a parameter too
shard_id int := 1;
BEGIN
SELECT nextval('devices_id_seq') % 1024 INTO seq_id;
SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis;
result := (now_millis - our_epoch) << 23;
result := result | (shard_id << 10);
result := result | (seq_id);
END;
$$ LANGUAGE PLPGSQL;
ALTER TABLE mytable ADD CONSTRAINT mytable_pkey PRIMARY KEY (id);
ALTER TABLE mytable ALTER COLUMN id SET DEFAULT id_generator();

------------
Удалить созданный ранее генератор

ALTER TABLE mytable DROP CONSTRAINT mytable_pkey;
ALTER TABLE mytable DROP COLUMN id;
ALTER TABLE mytable ADD COLUMN id SERIAL;
UPDATE mytable SET id = DEFAULT;
ALTER TABLE mytable ADD PRIMARY KEY (id);
DROP FUNCTION id_generator();

postgresql, кластеризация, узелки

Previous post Next post
Up