Может ли идентификатор автоинсюрмана когда-либо измениться от среднего значения транзакции при совершении коммита?
-
10-10-2019 - |
Вопрос
Возможность этого кажется мне чрезвычайно маловероятным из -за проблем, которые это может вызвать, но я подумал, что все равно задаю вопрос ...
Представьте себе транзакцию, в которой участвует идентификатор автоинскручения и назначается значение. До совершения задействованного кода кэширует копия назначенного идентификатора для последующей ссылки. Тогда транзакция совершена.
Предполагая, что нет прямого вмешательства клиента (удаление или изменение записи), есть ли какая -либо база данных или ситуация, которая когда -либо автоматически изменяет значение идентификатора сразу после совершения, делая кэшированный идентификатор неправильным? Всегда ли безопасно кэшировать ID в середине транзакции?
Один гипотетический случай, когда я могу себе представить, что это происходит, если какая-то реализация RDBMS необъяснимо решила, что необходимо иметь значения автостоинкремента без пробела и зависимых от времени (поскольку я вижу много примеров людей, желающих этого). В этом гипотетическом случае я могу представить себе, как может быть сделано некоторые магические перетасовки идентификаторов, чтобы заполнить пробелы, вызванные откатами в ассигновании после ID в другой транзакции (или другой причине пробела). Это лишает недействительного кэшированного значения.
Кто -нибудь знает о такой реализации или другой убийце кеша?
Решение
Реализация сгенерированных значений ID обычно включает увеличение значения счетчика в короткой атомной операции. Это значение затем используется для запрашивающей транзакции, и даже если эта транзакция откатится назад, зарезервированное значение никогда не будет возвращено в пул свободных значений. Так что в этом свете я не думаю, что описанная ситуация очень вероятно. Кроме того, в программах типа PL/SQL вам действительно нужно, чтобы сгенерированное значение было правильным, чтобы вставить другие зависимые строки в детские таблицы.
Что касается людей, которые хотят, чтобы идентификационные значения без разрыв: единственная цель автоинскрущения/суррогатного ключа-создать искусственную идентификацию для ряда. Это не должно иметь ничего общего с определением порядка, в котором были созданы строки. Есть гораздо лучшие способы сделать это, например, с использованием временной метки создания.
Другие советы
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
.