2013-02-16 5 views
5

Wir haben vor kurzem bei gleichzeitiger Einsätze in einem unserer sal Server-Tabellen von mehreren Clients ein Problem konfrontiert sind. Ich hoffe ihr könnt uns helfen.SQL Server - Gleichzeitige Inserts auf den Tisch von mehreren Clients - Überprüfen End- und Block

Wir verwenden Stored Procedure die Transaktionen zu tun. In dieser gespeicherten Prozedur berechnen wir für jede Transaktion den Gesamtumsatz bisher. Wenn der Gesamtumsatz weniger als das festgelegte Limit ist, wird die Transaktion erlaubt, . Andernfalls wird die Transaktion abgelehnt.

es funktioniert die meiste Zeit. Aber manchmal, wenn mehrere Clients versuchen, die Transaktion genau zur gleichen Zeit auszuführen, schlägt die Grenzwertprüfung fehl, da beide Transaktionen ausgeführt werden.

Können euch vorschlagen, wie wir effektiv die Grenze die ganze Zeit durchsetzen können? Gibt es einen besseren Weg, das zu tun?

Danke!

+1

Bitte geben Sie Ihre Tabellenstruktur und Beispieldaten an. Ist das eingestellte Limit für alle Transaktionen konstant? –

+0

Als eine Ahnung könnte das Problem gelöst werden, wenn Sie die gespeicherte Prozedur viel schneller ausführen. Bei einer gespeicherten 100-ms-Prozedur sind Kollisionen äußerst selten. Wenn Sie die Abfrage und die Tabellendefinition veröffentlichen, können Sie einen Index vorschlagen, der die Gesamtberechnung sehr schnell macht. – Andomar

+0

finden Sie die Tabellenstruktur. In dieser Summe (Einsatz) sollte für jede Betnummer 1000 nicht überschritten werden. Diese 1000 Grenze wird in einer anderen Tabelle gespeichert. \t [SlipID] [Bigint] IDENTITY (1,1) NOT NULL, \t [TillID] [int] NOT NULL, \t [Barcode] [varchar] (30) NOT NULL, \t [GamingDate] [Datum] NOT NULL, \t [DrawID] [int] NOT NULL, \t [BetNumber] [Tinyint] NOT NULL, \t [CurrencyID] [int] NOT NULL, \t [Stake] [dezimal] (9, 2) NOT NULL , \t \t [SlipTime] [Datetime] NOT NULL, – sammy

Antwort

5

Ich glaube nicht, es möglich ist, dies deklarativ zu tun.

Wenn alle Einsätze garantiert durch die gespeicherte Prozedur gehen und die SaleValue einmal nicht aktualisiert wird eingefügt dann sollte die folgende Arbeit (I aus Tabellen- und Spaltennamen, da diese nicht in der Ausgangsfrage geliefert wurden)

DECLARE @SumSaleValue MONEY 

BEGIN TRAN 

SELECT @SumSaleValue = SUM(SaleValue) 
FROM dbo.Orders WITH (UPDLOCK, HOLDLOCK) 
WHERE TransactionId = @TransactionId 

IF @SumSaleValue > 1000 
    BEGIN 
    RAISERROR('Cannot do insert as total would exceed order limit',16,1); 
    ROLLBACK; 
    RETURN; 
    END 

/*Code for INSERT goes here*/ 

COMMIT 

Die HOLDLOCK gibt serialisierbare Semantik und sperrt den gesamten Bereich passend zu TransactionId und UPDLOCK verhindert, dass zwei gleichzeitige Transaktionen den gleichen Bereich sperren, wodurch das Risiko von Deadlocks verringert wird.

Ein Index für TransactionId,SaleValue wäre am besten, um diese Abfrage zu unterstützen.

+1

+1 Clever! Vielleicht ein bisschen zu schlau, da es für jeden, der den Code bearbeitet, die Messlatte höher legt. Möglicherweise ist es eine gute Idee, die Transaktion zu schließen, bevor die Prozedur zurückkehrt. – Andomar

+0

@Andomar - Danke. Vergessen dass! –

+0

Danke Martin! Es half ... Aber wir fuhren fort, zusammenfassende Tabellen mit Gesamtwert zu erstellen, erhalten plus oder minus für jede Transaktion.Auch die Verkaufstabellen sind riesig und jedes Mal, wenn die Abfrage der Tabelle zur Berechnung der Gesamtsumme Zeit in Anspruch nimmt, werden zu viele Einfügungen und Indizes zu schnell fragmentiert. Also haben wir uns entschieden, diese Übersichtstabelle zu haben ... Bis jetzt hilft es ... Vielen Dank! – sammy

Verwandte Themen