Я постараюсь объяснить свою проблему как можно более подробно, и я буду признателен за любую помощь / предложение. Моя проблема рассматривает тупик, вызванный двумя запросами (одна вставка и одно обновление). Я использую MS-SQL Server 2008
У меня есть два приложения, используя одну и ту же базу данных:
, веб-приложение вставляет записи отображения, не используя транзакцию, в то время как Приложение Windows Service вычисляет впечатления при использовании isolationLevel.readuncommed
транзакции. Сохраненная процедура в приложении Windows Service делает что-то подобное:
Сервис Windows сохранена процедура:
Курортные петли все впечатления, которые имеют флаг ISCAlculated
, установленный на false и date ISCALCULL flag to true на впечатлениях, которые имеют дату
DECLARE @nowTime datetime = convert(datetime, @now, 21)
DECLARE dailyCursor CURSOR FOR
SELECT Daily.dailyId,
Daily.spentDaily,
Daily.impressionsCountCache ,
SUM(Impressions.amountCharged) as sumCharged,
COUNT(Impressions.impressionId) as countImpressions
FROM Daily INNER JOIN Impressions on Impressions.dailyId = Daily.dailyId
WHERE Impressions.isCharged=0 AND Impressions.showTime < @nowTime AND Daily.isActive = 1
GROUP BY Daily.dailyId, Daily.spentDaily, Daily.impressionsCountCache
OPEN dailyCursor
DECLARE @dailyId int,
@spentDaily decimal(18,6),
@impressionsCountCache int,
@sumCharged decimal(18,6),
@countImpressions int
FETCH NEXT FROM dailyCursor INTO @dailyId,@spentDaily, @impressionsCountCache, @sumCharged, @countImpressions
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE Daily
SET spentDaily= @spentDaily + @sumCharged,
impressionsCountCache = @impressionsCountCache + @countImpressions
WHERE dailyId = @dailyId
FETCH NEXT FROM dailyCursor INTO @dailyId,@spentDaily, @impressionsCountCache, @sumCharged, @countImpressions
END
CLOSE dailyCursor
DEALLOCATE dailyCursor
UPDATE Impressions
SET isCharged=1
WHERE showTime < @nowTime AND isCharged=0
Веб-приложение, сохраненная процедура:
Эта процедура довольно проста, она просто вставила запись в таблицу Отказ Вот укороченный фрагмент кода:
INSERT INTO Impressions
(dailyId, date, pageUrl,isCalculated) VALUES
(@dailyId, @date, @pageUrl, 0)
Код
Код, который вызывает эти хранимые процедуры, довольно просто, он просто создает команды SQL, передаваемые необходимые параметры и выполняют их
//i send the date like this
string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture);
SqlCommand comm = sql.StoredProcedureCommand("storedProcName",
parameters, values);
, я очень часто испытываю тупики ( Исключения возникают в веб-приложении, а не на службе Windows), а после использования SQL-профилировщика я обнаружил, что тупики, вероятно, происходят из-за этих двух запросов (у меня нет большого опыта в анализе данных профилирования).
Последние данные трассировки, собранные из профилировщика SQL Server Server, можно найти внизу этого вопроса
, теоретически эти два хранимых процедурах должны быть в состоянии работать вместе, потому что первый вставляет записи один на одну с датой = Datetime.now, а второй вычисляет впечатления, которые имеют дату Редактировать: Вот код выполняется в приложении Windows Service: Редактирование: Я добавил индексы на обоих таблицах, как предложено Martin Smith, как это: и На данный момент нет исключений, сообщите позже редактирование: К сожалению, это не решило проблему тупика. Я начну след тупика в Profiler, чтобы посмотреть, будут ли тупики такими же, как раньше. Отредактируйте: вставил новый след (мне это выглядит так же, как и предыдущий), не смог бы захватить экран плана исполнения (слишком большой), но здесь - XML из План выполнения . И вот скриншот плана исполнения вставки Query: Редактировать: После предложений от Джонатана Дикинсона: Обновление: Время выполнения запросов было уменьшено после последних изменений, но количество исключений нет. Надеюсь, последнее обновление: Изменения, предложенные Мартином Смитом, теперь в прямом эфире, вставьте запрос вставки теперь использует не кластерный индекс и теоретически это должно исправить проблему. На данный момент никаких исключений не сообщалось (удерживая мои пальцы скрещенными) SQL sql = new SQL();
DateTime endTime = DateTime.Now;
//our custom DAL class that opens a connection
sql.StartTransaction(IsolationLevel.ReadUncommitted);
try
{
List
CREATE NONCLUSTERED INDEX [IDX_Daily_DailyId] ON [dbo].[Daily]
(
[daily] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IDX_Impressions_isCharged_showTime] ON [dbo].[Impressions]
(
[isCharged] ASC,
[showTime] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO