Sql Server: удаление фрагментов по-прежнему заполняет журнал транзакций; при неудаче откатывается все удаления - почему? - PullRequest
1 голос
/ 30 апреля 2010

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

У нас есть работа, которая использует данные из 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%.

ТИА.

Ответы [ 2 ]

0 голосов
/ 03 мая 2010

Я перепробовал несколько вещей, но все удаления удаляются. Я добавил 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));

Вызывается из этого т-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 голосов
/ 30 апреля 2010

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

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

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

...