Ich denke es ist nicht eine Frage, welche besser ist, da Daten bereits alt/ungültig ist, sobald es den Client erreicht. Das Anzeigen einer Reserviertabelle kann nützlich sein, um einen groben Überblick über die vorgenommenen Reservierungen zu erhalten, aber in der nächsten Sekunde könnte es ganz anders aussehen. Sie möchten die Rennbedingungen beseitigen. Eine gute Architektur ist notwendig, um damit zu beginnen.
Eine Möglichkeit, dies zu tun ist, das Ticket [1] zu 'reservieren'. Die Anwendung fragt nach einem Ticket, das bei den übereinstimmenden Kriterien verfügbar ist. An dieser Stelle ist bekannt, ob das Ticket verfügbar ist oder nicht. Wenn es verfügbar war, war es bereits reserviert. Dies vermeidet Mehrfachreservierungen für ein Ticket. Die nächste Reservierung (gleiche Operation/Aktion) führt dazu, dass ein anderes Ticket reserviert wird. Sie können diesem Ticket später jederzeit Informationen hinzufügen (z. B. den Besitzer des Tickets und seine Informationen). Tickets, denen keine Informationen beigefügt sind, werden nach einer bestimmten Anzahl von Minuten ablaufen und in den Pool zurückkehren. Diese Tickets können wieder 'reserviert' werden [1].
[1] Um Mehrfachzuweisungen zu vermeiden, verwenden Sie optimistic locking. Um die Frage zu beantworten, würde ich DataReader
sagen. Es hält die Datenbankkommunikation auf ein Minimum (Laden und Sperren), so dass Updates so schnell wie möglich verarbeitet werden können. Denken Sie nur daran, dass Sie Probleme mit Nebenläufigkeit nicht lösen können. Es ist die Gesamtlösung, die zählt.
Beispiel
Ich weiß nicht die Anforderungen, aber da es ein Interview Frage ist werde ich ein Beispiel geben. Nimm das nicht als goldene Regel, aber von der Spitze meines Kopfes würde es in etwa so sein:
(falls erforderlich) Zuerst wird dem Benutzer ein Bildschirm angezeigt, dass noch Tickets im System übrig sind reserviert. Öffnen Sie eine Verbindung und einen Leser, um die Anzahl der verfügbaren Tickets für die Reservierung zu lesen. Schließen Sie den Reader und die Verbindung. Der Benutzer fährt mit dem nächsten Bildschirm fort.
SELECT COUNT(*)
FROM [Tickets]
WHERE ([LastReserved] IS NULL OR [LastReserved] <= DATEADD(MINUTE, GETDATE(), @ticketTimeout))
AND [TickedAssignedToUserId] IS NULL;
Der Benutzer fordert eine x-Menge von Tickets und fährt mit dem nächsten Bildschirm. In diesem Moment prüft das System mit optimistischer Sperrung, ob genügend Tickets verfügbar sind. Einfach eine Verbindung öffnen und die folgende Abfrage ausführen (mit der Transaktion!):
UPDATE TOP(@numberOfTicketsRequested) [Tickets]
SET [LastReserved]=GETDATE()
WHERE ([LastReserved] IS NULL OR [LastReserved] <= DATEADD(MINUTE, GETDATE(), @ticketTimeout))
AND [TickedAssignedToUserId] IS NULL;
Die Anzahl der Zeilen sollten gleich @numberOfTicketsRequested betroffen sein. Wenn dies der Fall ist, übergeben Sie die Transaktion und erhalten Sie die Ticket-ID. Andernfalls rollback und sag dem Benutzer, dass keine Tickets mehr verfügbar sind. An dieser Stelle benötigen wir die Datensatzinformationen, also möchten Sie vielleicht auch die Kennung erhalten.
An diesem Punkt erhält der Benutzer @ticketTimeout
Minuten Zeit, um ihre Benutzerdetails einzugeben. Wenn es richtig gemacht, kann die folgende Abfrage ausgeführt werden:
UPDATE TOP(@numberOfTicketsRequested) [Tickets]
SET [TickedAssignedToUserId][email protected]
WHERE [TicketId][email protected] AND [LastReserved][email protected] AND [TickedAssignedToUserId] IS NULL;
Wenn der Benutzer hat länger gedauert als, sagen wir 10 Minuten und jemand anderes mit dem gleichen Ticket erneut angefordert, dann wird der LastReserved
Zeitstempel geändert hat. Wenn der erste Benutzer versucht hat, das Ticket mit seinen Details zu reservieren, stimmt das Update nicht mehr mit dem ursprünglichen LastReserved
Zeitstempel überein, und das Update zeigt nicht genügend betroffene Zeilen (= Rollback) an. Wenn es mit der Anzahl der betroffenen Zeilen übereinstimmt, hat der Benutzer die Tickets erfolgreich reserviert (= Festschreibung).
Beachten Sie, dass keine Ticketinformationen mit Ausnahme der Ticketbezeichner die Anwendung erreicht haben. Ich habe auch keine Benutzerregistrierung aufgenommen. Es werden keine vollständigen Tabellen übergeben, und Sperren werden nur minimal verwendet (nur für zwei kurze Aktualisierungen).
Danke für den Link zum optimistischen Sperren. Concurrency wäre damit definitiv gelöst. Wenn viele Benutzer versuchen, die verfügbaren Tickets abzurufen und dann versuchen, das Ticket zu buchen. Da bei DataReader die Verbindung immer geöffnet bleibt. Dies beeinträchtigt nicht die Belastung des Datenbankservers. Wenn ich Disconnected Architecture verwende, kann Locking angewendet werden und das Laden auf dem Datenbankserver wäre auch weniger. Ja, Speicherprobleme wären vorhanden, aber es wird mehr auf das Leistungsproblem, den Datenbankserver oder das Speicherproblem kommen. – user2432715
Als Nebenbemerkung: 'DataReader' implementiert' IDisposable', sodass Ressourcen (Verbindung) an den Verbindungspool zurückgegeben werden. Zu diesem Zeitpunkt können aufgrund der Verbindung, die verfügbar geworden ist, andere Lese-/Schreibvorgänge verwendet werden, wodurch der Durchsatz verbessert wird. Beachten Sie, dass es sich bei der genannten Sperre nicht um eine herkömmliche Sperre handelt (sie wird erst gesperrt, wenn Sie sie wieder freigeben). – Caramiriel
So sind die folgenden Schritte, um den DataReader effizient zu nutzen: 1. Öffnen Sie die Verbindung 2. Zeigen Sie die Daten dem Benutzer mit DataReader. 3. Schließen Sie die Verbindung. (Hier wird die Ressource frei sein) Jetzt kommt die Aktualisierung. Der Benutzer wird nun einen Datensatz aktualisieren. 4. Ooen Connection erneut 5. Verwenden Sie den Daten-Reader, um den jeweiligen Datensatz zu aktualisieren. 5. Schließen Sie es. Verriegelung entsprechend angewendet – user2432715