Domanda

La possibilità che ciò accada sembra estremamente improbabile per me a causa dei problemi che potrebbe causare, ma ho pensato io chiedo avevo la questione in ogni caso ...

Immaginate una transazione in cui un ID AutoIncrement è coinvolto e viene assegnato un valore. Prima di compiere, il codice coinvolto memorizza nella cache una copia della ID assegnato per riferimento futuro. Poi la transazione è impegnata.

Supponendo che nessun intervento cliente diretto (soppressione o alterazione del record), non v'è alcun database o situazione che altererebbe mai automaticamente il valore ID immediatamente dopo COMMIT, rendendo l'ID cache non corretta? E 'sempre sicuro di memorizzare nella cache l'ID metà transazione?

Un caso ipotetico in cui posso immaginare che ciò accada è se qualche implementazione RDBMS inspiegabilmente ha deciso che era necessario avere gapless e dipendenti dal tempo valori autoincremento (poiché vedo molti esempi di persone che vogliono questo). In questo caso ipotetico, posso immaginare un po 'magica rimescolamento di ID potrebbe essere fatto per colmare le lacune causate da rollback post-ID-assegnazione a un'altra operazione (o altro causer gap). Questo invaliderebbe il valore memorizzato nella cache.

Qualcuno sa di una tale realizzazione, o altro nascondiglio assassino?

È stato utile?

Soluzione

L'attuazione dei valori ID generato solito comporta incrementare un valore del contatore in un breve operazione atomica. Questo valore viene quindi utilizzato per la transazione dal richiedente e, anche se tale operazione avrebbe rollback, il valore riservato non sarà mai restituito al pool di valori liberi. Quindi, in questa luce non penso la situazione descritta è molto probabile. Inoltre, in PL / SQL tipo di programmi è davvero necessario il valore generato per essere di destra per inserire altre righe dipendenti a tabelle figlio.

Come per le persone che mancano valori senza pause id tempo ordinato: il solo scopo di chiave autoincrement / surrogata è creare un'identificazione artificiale per una riga. Esso dovrebbe avere nulla a che fare con la determinazione dell'ordine in cui sono state create le righe. Ci sono modi migliori per farlo, ad esempio utilizzando un timestamp di creazione.

Altri suggerimenti

supporti PostgreSQL DEFERRED trigger che possono alterare i dati sulla 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;

La prima SELECT (a destra prima del COMMIT) ritorna 1, il secondo (subito dopo il COMMIT) restituisce 11.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top