2010-04-30 2 views
1

Вот мой сценарий: у нас есть база данных, назовем ее Logging, с таблицей, содержащей записи из Log4Net (через MSMQ). Режим восстановления db имеет значение Simple: нам не нужны журналы транзакций - они могут перевернуться.Sql Server: удаление каналов по-прежнему заполняет журнал транзакций; при отказе все удаления откатываются - почему?

У нас есть работа, которая использует данные из sp_spaceused, чтобы определить, встретили ли мы порог определенного размера. Если порог превышен, мы определяем, сколько строк нужно удалить, чтобы уменьшить размер до x процентов от этого порога. (В стороне, я использую exec sp_spaceused MyLogTable, TRUE, чтобы получить количество строк и приблизительное приближение их среднего размера, хотя я не уверен, что это лучший способ сделать это. Но это другая проблема.)

затем я пытаюсь кусок удаляет (скажем, 5000, в то время), обернув вызов к sproc, который в основном делает это:

DELETE TOP (@RowsToDelete) FROM [dbo].[MyLogTable] 

, пока я удалил то, что должно быть удалено.

В этом случае проблема: если у меня есть много строк для удаления, файл журнала транзакций заполняется. Я могу смотреть его вырастить, запустив

dbcc sqlperf (logspace) 

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

Я пробовал явно отключать неявные транзакции, обертывая каждый оператор DELETE в BEGIN и COMMIT TRAN, но безрезультатно: удалены все удаленные куски или вообще ничего.

Я знаю простой ответ: Сделайте свой файл журнала достаточно большим, чтобы обрабатывать максимально возможное количество записей, которые вы когда-либо удаляли, но все же, почему это рассматривается как одна транзакция?

Извините, если я пропустил что-то легкое, но я просмотрел множество сообщений о том, как увеличивается файл журнала, режимы восстановления и т. Д., И я не могу понять это.

Другое: после того, как работа не удалась, файл журнала остается на 95-100 процентов в течение некоторого времени, прежде чем он опустится. Тем не менее, если я запускаю

checkpoint 
dbcc dropcleanbuffers 

он падает до примерно 5% использования.

TIA.

ответ

0

Файл журнала в простой модели восстановления автоматически усекает каждую контрольно-пропускную точку. Вы можете вызвать контрольную точку вручную, как и в конце цикла, но вы также можете выполнять ее на каждой итерации. Частота контрольных точек по умолчанию определяется автоматически сервером sql на основе настройки интервала восстановления.

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

Hm .. если журнал растет и не усекает автоматически, он также может указывать на то, что транзакция выполняется за пределами цикла. Можете ли вы select @@trancount перед вашей петлей и, возможно, с каждой итерацией, чтобы узнать, что происходит?

+1

Piotr, спасибо за ваше предложение s. На самом деле, я выполняю «драйвер» sproc из Query Analyzer. Ваш вопрос о внешней транзакции заставляет меня задаться вопросом, задает ли Query Analyzer по умолчанию implicit_transactions? Я проверил Profilier и не видел этого. Тем не менее, я попробую еще раз с SET IMPLICIT_TRANSACTIONS OFF в сеансе Query Analyzer и посмотреть, не влияет ли это (все или некоторые откатываются при отказе). Я отвечу, когда проведу этот тест. Спасибо, Пол –

0

Ну, я пробовал несколько вещей, но все же все удаляются, откатываются назад. Я добавил printint @@TRANCOUNT как до, так и после удаления, и я получаю нуль в качестве счетчика. Тем не менее, при сбое все удаления откатываются .... Я добавил SET IMPLICIT_TRANSACTIONS OFF в нескольких местах (в том числе в моем первоначальном вызове из Query Analyzer, но это, похоже, не помогает. Это тело хранимой процедуры, которая вызывается (Я поставил @RowsToDelete 5000 и 8000):

SET NOCOUNT ON; 
    print N'@@TRANCOUNT PRIOR TO DELETE: ' + CAST(@@TRANCOUNT AS VARCHAR(20)); 

    set implicit_transactions off; 
    WITH RemoveRows AS 
    (
    SELECT ROW_NUMBER() OVER(ORDER BY [Date] ASC) AS RowNum 
    FROM [dbo].[Log4Net] 
) 

    DELETE FROM RemoveRows 
    WHERE RowNum < @RowsToDelete + 1 

    print N'@@TRANCOUNT AFTER DELETE: ' + CAST(@@TRANCOUNT AS VARCHAR(20)); 

Он вызывается из этого T-SQL:.

WHILE @RowsDeleted < @RowsToDelete 
BEGIN 
EXEC [dbo].[DeleteFromLog4Net] @RowsToDelete 
SET @RowsDeleted = @RowsDeleted + @RowsToDelete 
Set @loops = @loops + 1 
print 'Loop: ' + cast(@loops as varchar(10)) 
END 

Я должен признать, что я озадачен я не БД гуру, но Я думал, что понял достаточно, чтобы понять это ....

+0

Ну, я действительно ненавижу это признавать, но в '@ RowsToDelete' я проходил через общее количество строк для удаления - не мой размер куска. Вздох. Еще несколько печатных заявлений и другой набор глаз поймали мою ошибку ... Проблема решена. –

Смежные вопросы