Может ли идентификатор автоинкремента когда-либо изменяться со значения средней транзакции при фиксации? - PullRequest
3 голосов
/ 13 января 2011

Возможность этого для меня представляется крайне маловероятной из-за проблем, которые он может вызвать, но я решил, что все равно задам вопрос ...

Представьте себе транзакцию, в которой задействован идентификатор автоинкремента изначение назначено.Перед COMMIT соответствующий код кэширует копию назначенного идентификатора для последующего использования.Затем транзакция фиксируется.

При условии отсутствия прямого вмешательства клиента (удаления или изменения записи), существует ли какая-либо база данных или ситуация, которая когда-либо автоматически изменяла бы значение идентификатора сразу после COMMIT, делая кэшированноеНеверный идентификатор?Всегда ли безопасно кэшировать идентификатор в середине транзакции?

Один гипотетический случай, когда я могу себе представить, что это происходит, - это если какая-то реализация СУБД необъяснимым образом решила, что необходимо иметь бесщелевые и зависящие от времени значения автоинкремента (так как я вижу много примеров людей, желающих этого).В этом гипотетическом случае я могу представить, что может быть сделано какое-то волшебное перетасовывание идентификаторов, чтобы заполнить пробелы, вызванные откатами после присвоения идентификатора в другой транзакции (или другой пробел, вызывающий разрыв).Это сделает недействительным кэшированное значение.

Кто-нибудь знает о такой реализации или о другом убийце кэша?

Ответы [ 2 ]

4 голосов
/ 13 января 2011

Реализация сгенерированных значений идентификаторов обычно включает в себя увеличение значения счетчика в короткой атомарной операции.Затем это значение используется запрашивающей транзакцией, и даже если эта транзакция откатится, зарезервированное значение никогда не будет возвращено в пул свободных значений.Так что в этом свете я не думаю, что описанная ситуация очень вероятна.Кроме того, в программах типа pl / sql вам действительно нужно, чтобы сгенерированное значение было правильным для вставки других зависимых строк в дочерние таблицы.

Что касается людей, которым нужны упорядоченные по времени значения id без пробелов:единственная цель автоинкрементного / суррогатного ключа - создать искусственную идентификацию для ряда.Это не должно иметь ничего общего с определением порядка, в котором были созданы строки.Есть гораздо лучшие способы сделать это, например, используя метку времени создания.

1 голос
/ 13 января 2011

PostgreSQL поддерживает DEFERRED триггеры, которые могут изменять данные на COMMIT.

CREATE TABLE test_autoinc (id BIGSERIAL);

CREATE TABLE test_other (id BIGSERIAL);

CREATE FUNCTION prc_update_autoinc()
RETURNS TRIGGER
AS
$$
BEGIN
        UPDATE  test_autoinc
        SET     id = id + 10;
        RETURN  NEW;
END;
$$
LANGUAGE 'plpgsql';

CREATE CONSTRAINT TRIGGER
        trg_other_ai
AFTER INSERT
ON      test_other
DEFERRABLE
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE prc_update_autoinc();

BEGIN TRANSACTION;

INSERT
INTO    test_autoinc
DEFAULT VALUES;

INSERT
INTO    test_other
DEFAULT VALUES;

SELECT  *
FROM    test_autoinc;

COMMIT;

SELECT  *
FROM    test_autoinc;

Первый SELECT (прямо перед COMMIT) возвращает 1, второйодин (сразу после COMMIT) возвращает 11.

...