I think das Problem, das ich habe, ist ein Problem mit dem gemeinsamen Zugriff, aber ich denke, ich verstehe SQL Server-Transaktionen nicht gut genug, um sicher zu sein, was zu tun ist.Fremdschlüsselkonfliktkonflikt Concurrency-Problem
Ich habe eine gespeicherte Prozedur, die eine neue Zeile in eine Tabelle einfügt, dann die ID von diesen INSERT
erstellt verwendet eine Aufzeichnung in einer anderen Tabelle zu erstellen, die eine Fremdschlüsseleinschränkung für RID hat:
INSERT INTO tbl_Registrations ...
DECLARE @RID int;
--get newly-created registration ID
SET @RID=(SELECT MAX(RID) FROM tbl_Registrations WHERE ...);
INSERT INTO tbl_RegistrationCertificates VALUES (@RID, 9);
Diese gespeicherte Prozedur wird von einer Benutzerinteraktion auf einer Website aufgerufen, und jedes Mal, wenn ich sie getestet habe, funktioniert es einwandfrei. jeder einmal in eine Weile jedoch, werde ich eine E-Mail von unserem Fehler-Handler erhalten, mit folgender Ausnahme:
System.Data.SqlClient.SqlException (0x80131904): The INSERT statement conflicted with the FOREIGN KEY constraint "FK_tbl_RegistrationCertificates_tbl_Registrations".
The conflict occurred in ... table "dbo.tbl_Registrations", column 'RID'.
The statement has been terminated.
Aber entweder meine Benutzer persistent in klicken Sie auf die Schaltfläche „Aktualisieren“, bis sie eine Veränderung zu sehen, oder die Transaktion wird ausgeführt, obwohl die Nachricht The statement has been terminated
lautet, weil ich mit anderen Informationen aus der E-Mail sehen kann, dass beide Tabellen tatsächlich aktualisiert wurden.
Ich weiß, ich bin nicht eine Tonne Informationen hier, aber die großen Fragen zu geben, die ich keine Antworten auf finden kann:
- Hat das Semikolon am Ende einer Anweisung tut alles in T -SQL? Mir ist gerade aufgefallen, dass am Ende der INSERT-Anweisung kein Semikolon steht. (Ich mache sie normalerweise aus Gewohnheit, aber ich arbeite an Systemen, die andere Leute gebaut haben.)
- Sieht dies für Leute, die mehr über SQL Server als ich wissen, wie eine Nebenläufigkeitsproblem?
- Wenn es wie ein Concurrency-Problem aussieht, kann ich Transaktionen verwenden, um es zu reduzieren, und wie mache ich das?
EDIT: Ich habe gerade festgestellt, dass der SP ist nicht das, was den Fehler wirft schließlich. Es gibt einen anderen Ort auf der Website, der eine Einfügung durchführt, ohne zu überprüfen, ob die RID existiert. Trotzdem bin ich froh, dass ich die Fragen gestellt habe, weil ich die Antworten sonst nicht gewusst hätte.
Ah, 'SCOPE_IDENTITY()' ist nicht etwas, was ich vorher gesehen habe; Das ist sehr hilfreich. Offensichtlich gab es eine Menge Code, den ich aus Gründen der Kürze weggelassen habe, aber der zweite "INSERT" wird nur ausgeführt, wenn andere Kriterien auf der Basis der Parameter des SP erfüllt sind. Macht eine Transaktion in diesem Fall noch Sinn? –
Eine weitere Frage: Was ist der Unterschied zwischen Transaktionen und Batch-Separatoren? "GO" gegen "BEGIN TRANSACTION ... COMMIT TRANSACTION"? –
Eine Transaktion gruppiert mehrere Anweisungen logisch so, dass sie entweder erfolgreich sind oder als eine fehlgeschlagen sind. Wenn in meinem obigen Code "INSERT" bis "_tbl_RegistrationCertificates_" aus irgendeinem Grund fehlschlagen, wird auch "INSERT" auf "_tbl_Registrations_" zurückgesetzt. Transaktionen helfen Ihnen, einen logisch konsistenten Zustand beizubehalten, wenn eine Gruppe von Anweisungen alle als eine Operation behandelt werden soll (alles zwischen 'BEGIN' und' COMMIT'). Andererseits sagt 'GO' den SQL Server-Tools nur, dass sie eine Reihe von Anweisungen ausführen sollen. –