开发者

Can an autoincrement ID ever change from the mid-transaction value upon commit?

开发者 https://www.devze.com 2023-02-04 18:50 出处:网络
The possibility of this happening seems extremely unlikely to me because of the problems it could cause, but I figured I\'d ask the question anyway...

The possibility of this happening seems extremely unlikely to me because of the problems it could cause, but I figured I'd ask the question anyway...

Imagine a transaction where an autoincrement ID is involved and a value is assigned. Prior to COMMIT, the involved code caches a copy of the assigned ID for later reference. Then the transaction is committed.

Assuming no direct client intervention (deletion or altering of the record), is there any database or situation that would ever automatically alter the ID value immediately upon COMMIT, making the cached ID incorrect? Is it always safe to cache the ID mid-transaction?

One hypothetical case where I can imagine this happening is if some RDBMS implementation inexplicably decided it was necessary to have gapless and time-dependent autoincrement values (since I see many examples of people wanting this). In this hypothetical case, I can imagine some magical shuffling of IDs might be done to f开发者_开发问答ill in gaps caused by post-ID-assignment rollbacks in another transaction (or other gap causer). This would invalidate the cached value.

Anyone know of such an implementation, or other cache killer?


The implementation of generated id values usually involves incrementing a counter value in a short atomic operation. This value is then used for by the requesting transaction and even if that transaction would roll back, the reserved value will never be given back to the pool of free values. So in this light I dont think the situation described is very likely. Also, in pl/sql type of programs you really do need the generated value to be right in order to insert other dependent rows to child tables.

As for the people who are wanting time-ordered gapless id values: the sole purpose of autoincrement/surrogate key is to create an artificial identification for a row. It should have nothing to do with determining the order in which rows were created. There are far better ways to do this, for example using a creation timestamp.


PostgreSQL supports DEFERRED triggers which can alter the data on 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;

The first SELECT (right before the COMMIT) returns 1, the second one (right after the COMMIT) returns 11.

0

精彩评论

暂无评论...
验证码 换一张
取 消