Как выполнить sproc без транзакции?
У меня есть процесс очистки, который должен удалять около 8 миллионов строк в таблице каждый день (иногда больше). Этот процесс написан на C# и использует SMO для запроса схемы для индексов таблиц, отключая их перед выполнением sproc, который удаляет пакетами по 500 тыс. Строк.
Моя проблема в том, что вся операция живет внутри транзакции. Sproc выполняется внутри TransactionScope, который сконфигурирован с TransactionScopeOption.Suppress (это выполняется вместе с другими вещами, каждый из которых запускает новый TransactionScope), который, как я думал, не разрешит транзакцию, и внутри sproc есть явные точки фиксации.
Часть C# процесса может быть обобщена следующим образом:
try {
DisableIndexes(table);
CleanTable(table);
}
finally {
RebuildIndexes(table);
}
И у sproc есть петля внутри, которая в основном:
DECLARE @rowCount bigint = 1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
WHILE @rowCount <> 0 BEGIN
DELETE TOP (@rowsPerBatch) Table
WHERE
ID <= @maxID
SET @rowCount = @@rowcount
END
Прошлой ночью этот процесс отключился через полчаса после его запуска, потребовалось полчаса для отката и еще полчаса для перестроения индекса... слишком много времени для нулевой работы...=(
Обновление: я запустил процесс для небольшой базы данных (и с небольшим таймаутом), и это не так, как я думал. Очевидно, процесс правильно удаляет строки и делает успехи, как я хочу. Тем не менее, журнал становится потребляемым. Поскольку я нахожусь в режиме ПРОСТОЙ базы данных, разве журнал не должен расти в этом случае? Или процесс удаления настолько быстр, что я не даю процессу, который фактически удаляет строки, время, необходимое для поддержания журнала в чистоте?
2 ответа
В зависимости от ваших обстоятельств вы можете использовать многораздельные представления вместо многораздельных таблиц. Что-то вроде:
create table A
(
X int,
Y int,
Z varchar(300),
primary key (X,Y),
check (X = 1)
)
create table B
(
X int,
Y int,
Z varchar(300),
primary key (X,Y),
check (X = 2)
)
create table C
(
X int,
Y int,
Z varchar(300),
primary key (X,Y),
check (X = 3)
)
go
create view ABC
as
select * from A
union all
select * from B
union all
select * from C
go
insert abc (x,y,z)
values (1,4,'test')
insert abc (x,y,z)
values (2,99,'test'), (3,123,'test')
insert abc (x,y,z)
values (3,15125,'test')
select * from abc
truncate table c
select * from abc
Если я правильно понимаю вашу проблему, вам нужны автоматическое раздвижное окно и разделенные таблицы.