2013-02-16 7 views
5

Мы недавно столкнулись с одной проблемой с одновременными вставками в одну из наших таблиц сервера sal из нескольких клиентов. Надеюсь, вы, ребята, сможете нам помочь.SQL Server - одновременное вложение в таблицу из нескольких клиентов - контрольный лимит и блок

Мы используем хранимую процедуру для совершения транзакций. В этой хранимой процедуре для каждой транзакции мы рассчитываем общий объем продаж до сих пор. Если общий объем продаж меньше установленного лимита, , то сделка будет разрешена. В противном случае транзакция будет отклонена.

он отлично работает много раз. Но иногда, когда несколько клиентов пытаются совершить транзакцию точно в одно и то же время, проверка ограничений не выполняется, как и транзакции.

Можете ли вы, ребята, предложить нам, как мы можем эффективно применять лимит все время? Есть ли лучший способ сделать это?

Спасибо!

+1

Просьба представить структуру вашей таблицы и примеры данных. Является ли установленная предел константой для всех транзакций? –

+0

Как бы то ни было, проблема может быть решена, если вы заставите хранимую процедуру работать намного быстрее. При 100-миллисекундной процедуре столкновения будут чрезвычайно редкими. Если вы разместите определение запроса и таблицы, мы можем предложить индекс, который делает общий расчет очень быстрым. – Andomar

+0

, пожалуйста, найдите структуру таблицы. В этой сумме (ставке) для каждого номера ставки не должно превышать 1000. Этот предел 1000 сохраняется в другой таблице. \t [SlipID] [BIGINT] IDENTITY (1,1) NOT NULL, \t [TillID] [INT] NOT NULL, \t [Barcode] [VARCHAR] (30) NOT NULL, \t [GamingDate] [дата] NOT NULL, то \t [DrawID] [INT] NOT NULL, \t [BetNumber] [TINYINT] NOT NULL, \t [CurrencyID] [INT] NOT NULL, \t [Доля] [десятичное] (9, 2) NOT NULL , \t \t [SlipTime] [datetime] NOT NULL, – sammy

ответ

5

Я не думаю, что это можно сделать декларативно.

Если все вставки гарантированно пройти через хранимую процедуру и SaleValue не обновляется после вставки, то должно работать (я сделал имена таблиц и столбцов, поскольку они не были поставлены в первоначальном вопросе)

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 

HOLDLOCK дает сериализуемую семантику и блокирует весь диапазон, соответствующий TransactionId, а UPDLOCK предотвращает одновременную блокировку двух одновременных транзакций, что снижает риск взаимоблокировок.

Индекс на TransactionId,SaleValue будет лучше всего поддерживать этот запрос.

+1

+1 Умный! Может быть, слишком умный, поскольку он поднимает планку для любого, кто редактирует код. Может быть хорошей идеей закрыть транзакцию до возвращения процедуры. – Andomar

+0

@Andomar - Спасибо. Забыли это! –

+0

Спасибо Мартину! Это помогло ... Однако мы продолжили создание сводных таблиц с общим значением, получающим плюс или минус для каждой транзакции.Кроме того, таблицы продаж огромны, и каждый раз, запрашивая таблицу для вычисления общей суммы, требуется время, так как слишком много вставок и индексов получают фрагментацию слишком быстро .. поэтому мы решили получить эту сводную таблицу ... До сих пор ее помощь ... Благодаря! – sammy