Die SQL-Identität (automatische Nummerierung) wird auch bei einem Transaktions-Rollback erhöht

78

Ich habe eine .net-Transaktion mit einer SQL-Einfügung in eine SQL Server 2005-Datenbank. Die Tabelle hat einen Identitätsprimärschlüssel.

Wenn ein Fehler innerhalb der Transaktion auftritt, Rollback()wird aufgerufen. Die Zeileneinfügungen werden korrekt zurückgesetzt. Wenn ich jedoch das nächste Mal Daten in die Tabelle einfüge, wird die Identität erhöht, als ob das Zurücksetzen nie stattgefunden hätte. Es gibt also im Wesentlichen Lücken in der Identitätssequenz. Gibt es eine Möglichkeit, mit der Rollback()Methode die fehlende Identität zurückzugewinnen?

Nähere ich mich dem nicht richtig?

Muhan
quelle
Vorgeschlagene Bearbeitung: Ändern Sie "Autonummer" in "Identität". Autonumber ist die MS Access-Terminologie, während Identity der richtige Begriff in SQL Server ist.
Rick
Noch einen Beitrag als Antwort markieren? Warten Sie immer noch auf "Ihre Antwort"?
Kangkan
2
Die Antwort mit der höchsten Stimme macht keinen Versuch, die Frage der Vermeidung dieses Verhaltens tatsächlich zu beantworten. Unabhängig davon, ob der Ansatz korrekt ist oder nicht.
Jeff Swensen

Antworten:

105

Wenn Sie darüber nachdenken, sollte die Auto-Inkrement-Nummer nicht transaktional sein. Wenn andere Transaktionen warten müssten, um zu sehen, ob die automatische Nummer verwendet oder "zurückgesetzt" werden würde, würden sie von der vorhandenen Transaktion unter Verwendung der automatischen Nummer blockiert. Betrachten Sie beispielsweise meinen Pseudocode unten mit Tabelle A unter Verwendung eines Felds für die automatische Nummerierung für die ID-Spalte:

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

Wenn die Transaktion von Benutzer 2 eine Millisekunde nach der von Benutzer 1 beginnt, muss die Einfügung in Tabelle A warten, bis die gesamte Transaktion von Benutzer 1 abgeschlossen ist, um festzustellen, ob die automatische Nummer von der ersten Einfügung in A verwendet wurde.

Dies ist eine Funktion, kein Fehler. Ich würde empfehlen, ein anderes Schema zu verwenden, um automatische Nummern zu generieren, wenn diese eng aufeinander folgen müssen.

Jason Jackson
quelle
34

Wenn Sie darauf angewiesen sind, dass Ihre Identitätswerte lückenlos sind, dann ja - Sie machen es falsch. Der springende Punkt eines Ersatzschlüssels ist, keine geschäftliche Bedeutung zu haben .

Und nein, es gibt keine Möglichkeit, dieses Verhalten zu ändern (es sei denn, Sie rollen Ihr eigenes Autoincrement und leiden unter den Leistungsfolgen des Blockierens anderer Inserts).

Mark Brackett
quelle
16

Sie erhalten Lücken in Ihrer Sequenz, wenn Sie auch DELETEeine Zeile.

Sequenzen müssen eindeutig sein, aber nicht sequentiell. Die Tatsache, dass sie monoton zunehmen, ist nur ein Zufall bei der Umsetzung.

Bill Karwin
quelle
6

Soweit ich weiß, beanspruchen die Zeilen zum Einfügen die Autonummer und beim Rollback geht diese Nummer endgültig verloren. Wenn Sie darauf angewiesen sind, dass diese automatische Nummerierung in der Sequenzierung ausgeführt wird, sollten Sie den von Ihnen verwendeten Ansatz berücksichtigen.

Gavin Miller
quelle
6

Alle anderen Plakate, die sagen, dass sie sich keine Sorgen machen sollen und dass Sie Lücken bekommen sollten , haben Recht. Wenn die Zahl eine geschäftliche Bedeutung hat und diese Bedeutung nicht mit Lücken verbunden ist, verwenden Sie keine Identitätsspalte.

Zu Ihrer Information, wenn Sie aus irgendeinem Grund die Lücken entfernen möchten, haben die meisten Datenbanken die Möglichkeit, die automatische Nummerierung auf die Nummer Ihrer Wahl zu setzen. Es ist ein Schmerz im Arsch, und wenn Sie es regelmäßig tun müssen, sollten Sie definitiv kein Autonumber / Identity-Feld verwenden, wie oben erwähnt. Aber hier ist der Code, um es in SQL Server zu tun:

DBCC-CHECKIDENT ('Produkt', RESEED, 0)

Dadurch wird die Produkttabelle auf 1 zurückgesetzt. Wenn Sie jedoch Datensätze in der Tabelle haben, werden die bereits verwendeten ID-Werte offensichtlich übersprungen.) Andere RDBMS-Anbieter haben ihre eigene Syntax, aber der Effekt ist ungefähr der gleiche. Suchen Sie daher in den Systemhilfedateien oder im Internet nach "reseed identity" oder "reseed autonumber".

Nochmals: Dies ist für besondere Anlässe, nicht für den regelmäßigen Gebrauch. Legen Sie es nicht in eine gespeicherte Prozedur und lassen Sie uns alle dorthin kommen.

Ian Varley
quelle
6
Meiner Meinung nach sollte reseed nur verwendet werden, wenn Testdaten entfernt werden, um Live-Daten vorzubereiten. Und praktisch nie auf einem Produktionssystem.
HLGEM
3
" Wenn Sie jedoch Datensätze in der Tabelle haben, werden die bereits genommenen ID-Werte offensichtlich übersprungen. " - Ich habe die Erfahrung gemacht, dass dies nicht der Fall ist, und Sie erhalten eine doppelte Verletzung der Primärschlüsseleinschränkung, wenn Sie versuchen, eine zu erstellen INSERT (getestet unter SQL Server 2008). Sie müssen es auf den maximalen Identitätswert in der Tabelle setzen. Beim nächsten INSERT wird der nächste Wert (dh das Vorinkrement) zugewiesen.
Samgak
4

Ich glaube nicht, dass automatisch nummerierte Schlüssel sequentiell sein müssen. Tatsächlich glaube ich nicht, dass sie erforderlich sein können:

  • Transaktion a startet und fügt ein

  • Transaktion b startet und fügt ein

  • Transaktion a bricht ab

    Du bekommst ein Loch. nichts dagegen zu tun.

BCS
quelle
1

Muhan versucht, dies im Zusammenhang mit vielen gleichzeitigen Verbindungen zu betrachten, die diese Transaktion ausführen, und nicht nacheinander. Einige werden scheitern und andere werden erfolgreich sein. Sie möchten, dass sich SQL Server darauf konzentriert, die neuen Anforderungen beim Eingang auszuführen und keine lückenlose Identitätsspalte beizubehalten. IMO it (Lücken in den Werten) ist definitiv etwas, für das es sich nicht lohnt, Zeit zu investieren.

Eric Sabine
quelle
1

Nein. Sequenzimplementierungen verwenden eine autonome Transaktion. In Oracle befand sich die autonome Transaktion früher in der Datenbank, wird jetzt jedoch für den eigenen Gebrauch verfügbar gemacht (und häufig falsch verwendet).

PRAGMA AUTONOMOUS_TRANSACTION;' 
Brian
quelle