2013-02-16 6 views
5

Niedawno napotkaliśmy jeden problem z jednoczesnym wstawianiem do jednej z naszych tabel serwera sal od wielu klientów. Mam nadzieję, że możecie nam pomóc.Serwer SQL - Jednoczesne wstawianie do tabeli od wielu klientów - Sprawdzanie limitu i blokowanie

Używamy procedury przechowywanej do przeprowadzania transakcji. W tej procedurze przechowywanej dla każdej transakcji obliczamy dotychczas całkowitą sprzedaż. Jeśli łączna sprzedaż jest mniejsza niż ustawiony limit, , wówczas transakcja będzie dozwolona. W przeciwnym razie transakcja zostanie odrzucona.

to działa dobrze w większości razy. Ale czasami, gdy wielu klientów próbuje wykonać transakcję dokładnie w tym samym czasie, kontrola limitu kończy się niepowodzeniem, ponieważ obie transakcje są wykonywane.

Czy możecie zaproponować, w jaki sposób możemy skutecznie egzekwować limit przez cały czas? Czy istnieje lepszy sposób na zrobienie tego?

Dzięki!

+1

Proszę podać strukturę tabeli i przykładowe dane. Czy ustalony limit jest stały dla wszystkich transakcji? –

+0

Jako przeczucie, problem może zostać rozwiązany, jeśli procedura przechowywana uruchomi się znacznie szybciej. W przypadku procedury składowania o długości 100ms zdarza się wyjątkowo rzadko. Jeśli opublikujesz zapytanie i definicję tabeli, możemy zaproponować indeks, który bardzo szybko oblicza sumę. – Andomar

+0

proszę znaleźć strukturę tabeli. W tej sumie (stawka) dla każdego betnumber nie powinna przekraczać 1000. Ten 1000 limit jest przechowywany w innej tabeli. \t [SlipID] [bigint] IDENTITY (1,1) nie NULL \t [TillID] [Int] Za NULL \t [kreskowy] [varchar] (30) nie NULL \t [GamingDate] [data] Za NULL \t [DrawID] [Int] Za NULL \t [BetNumber] [tinyint] Za NULL \t [CurrencyID] [Int] Za NULL \t [Stake] [przecinku] (9: 2) nie NULL , \t \t [SlipTime] [datetime] NOT NULL, – sammy

Odpowiedz

5

Nie sądzę, że można to zrobić w sposób deklaratywny.

Jeśli wszystkie wkłady są gwarantowane, aby przejść przez procedury przechowywanej i SaleValue nie jest aktualizowana raz włożona wtedy następujące powinny działać (wymyśliłem nazwy tabel i kolumn nie zostały one dostarczone w pierwszym pytaniu)

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 

Numeruje się z semantyką nadającą się do szeregowania i blokuje cały zakres zgodny z TransactionId, a UPDLOCK zapobiega dwóm jednoczesnym transakcjom blokującym ten sam zakres, zmniejszając tym samym ryzyko wystąpienia zakleszczeń.

Indeks na temat TransactionId,SaleValue najlepiej będzie wesprzeć to zapytanie.

+1

+1 Sprytnie! Może trochę zbyt sprytnie, ponieważ podnosi poprzeczkę dla każdego, kto edytuje kod. Może być dobrym pomysłem, aby zamknąć transakcję przed powrotem procedury. – Andomar

+0

@Andomar - Dzięki. Zapomniałem tego! –

+0

Dzięki Martin! Pomogło to ... Jednak przystąpiliśmy do tworzenia tabel podsumowujących z całkowitą wartością plus lub minus dla każdej transakcji.Również tabele sprzedaży są ogromne i za każdym razem, gdy zapytanie o tabelę w celu obliczenia łącznej sumy zajęło trochę czasu, zbyt wiele wstawek i indeksów zostało podzielonych zbyt szybko. Tak więc zdecydowaliśmy się na taki zestawienie ... Jak dotąd pomoc ta ... Dzięki! – sammy

Powiązane problemy