Tożsamość SQL (autonumber) jest zwiększana nawet po wycofaniu transakcji

Mam transakcję. Net z wstawką SQL do bazy danych SQL Server 2005. Tabela ma klucz podstawowy tożsamości.

Gdy wystąpi błąd w transakcji, wywoływany jest Rollback(). Wstawki wiersza są odwrócone poprawnie, jednak przy następnym wstawieniu danych do tabeli tożsamość jest zwiększana tak, jakby cofnięcie nigdy nie miało miejsca. Więc Zasadniczo istnieją luki w sekwencji tożsamości. Czy jest jakiś sposób, aby metoda Rollback() odzyskała brakującą tożsamość?

Czy nie podchodzę do tego we właściwy sposób?
Author: marc_s, 2008-11-11

8 answers

Jeśli się nad tym zastanowić, numer auto-increment nie powinien być transakcyjny. Jeśli inne transakcje musiały poczekać, aby sprawdzić, czy auto-numer zostanie użyty lub "wycofany", zostaną zablokowane przez istniejącą transakcję przy użyciu auto-numeru. Na przykład, rozważmy mój kod psuedo poniżej z tabelą a, używając pola auto-number dla kolumny ID:

User 1
------------
begin transaction
insert into A ...
insert into B ...
update C ...
insert into D ...
commit


User 2
-----------
begin transaction
insert into A ...
insert into B ...
commit

Jeśli transakcja użytkownika 2 rozpocznie się milisekundę po transakcji użytkownika 1, wtedy ich wstawienie do tabeli A będzie musiało poczekaj, aż cała transakcja użytkownika 1 zostanie zakończona, aby sprawdzić, czy użyto auto-numeru z pierwszej wstawki do A.

To jest funkcja, nie błąd. Polecam użycie innego schematu do generowania auto-numerów, jeśli potrzebujesz, aby były ściśle sekwencyjne.

 105
Author: Jason Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-28 15:32:42

Jeśli zależy ci na tym, że twoje wartości tożsamościowe są puste, to tak - robisz to źle. Całość klucza zastępczego to ma mieć żadnego znaczenia biznesowego .

I, nie, nie ma sposobu, aby zmienić ten behaivor (pomijając zwijanie własnego autoincrement, i ponosząc konsekwencje wydajności blokowania innych wstawek).

 35
Author: Mark Brackett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-12 01:11:21

Masz luki w sekwencji, jeśli DELETE wiersz też.

Sekwencje muszą być unikalne, ale nie muszą być sekwencyjne. Fakt, że są one monotonicznie rosnące jest tylko fuksem realizacji.

 16
Author: Bill Karwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-11 23:56:53

Wszystkie inne plakaty, które mówią, żeby się tym nie martwić, i że ty powinieneś dostać luki, mają rację. Jeśli numer ma znaczenie biznesowe, a to znaczenie nie łączy się z lukami, nie używaj kolumny tożsamości.

FYI, jeśli z jakiegokolwiek powodu chcesz usunąć luki, większość baz danych ma sposób, aby przekierować automatyczną numerację do wybranego numeru. To wrzód na dupie, a jeśli uważasz, że potrzebujesz robić to regularnie, zdecydowanie nie powinieneś używać pole autonumber / identity, jak wspomniano powyżej. Ale oto kod do zrobienia tego w SQL server:

DBCC CHECKIDENT('Product', RESEED, 0)

Ustawia, że tabela produktów zaczyna się od 1 (chociaż jeśli masz rekordy w tabeli, to oczywiście pomija wartości ID, które są już zajęte.) Inni dostawcy RDBMS mają swoją własną składnię, ale efekt jest mniej więcej taki sam, więc poszukaj "reseed identity" lub "reseed autonumber" w plikach pomocy systemowej lub internetach.

Jeszcze raz: to jest na specjalne okazje, nie regularne stosowanie. Nie umieszczaj tego w procedurze składowanej i nie zmuszaj nas do tego.

 7
Author: Ian Varley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-14 02:15:24

Z tego co wiem wiersze do wstawiania twierdzą, że autonumber i po wycofaniu ta liczba jest tracona na dobre. Jeśli zależy ci na tym, że autonumber jest w sekwencjonowaniu, możesz rozważyć podejście, którego używasz.

 6
Author: Gavin Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-11 23:10:40

Nie wydaje mi się, że istnieje wymóg, aby klucze z automatycznym numerowaniem były sekwencyjne. W sumie to chyba nie można ich wymagać:

  • Transakcja a rozpoczyna i wstawia

  • Transakcja b rozpoczyna i wstawia

  • Transakcja a przerywa

    Masz dziurę. nic na to nie poradzę.

 4
Author: BCS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Muhan próbuje myśleć o tym w kontekście wielu jednoczesnych połączeń realizujących tę transakcję, a nie pojedynczo. Niektórym się nie uda, a niektórym się uda. Chcesz, aby SQL Server koncentrował się na uruchamianiu nowych żądań w miarę ich napływania, a nie na utrzymywaniu kolumny tożsamości bez luki. IMO to (luki w wartościach) jest zdecydowanie czymś, na co nie warto poświęcać czasu.

 1
Author: Eric Sabine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-11 23:22:39

Nie. Implmentacje sekwencyjne wykorzystują autonomiczną transakcję. W Oracle, autonomiczna transakcja była kiedyś wewnętrzna do dbms, ale teraz jest wystawiona na własny użytek (i jest często używana nieprawidłowo)

PRAGMA AUTONOMOUS_TRANSACTION;' 
 1
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-11 23:31:09