如何在没有事务的情况下执行 sproc
本文关键字:情况下 执行 sproc 事务 | 更新日期: 2023-09-27 18:30:32
我有一个清理过程,每天需要删除表中大约 800 万行(有时更多)。此过程是用 C# 编写的,并使用 SMO 查询表索引的架构,在执行批量删除 500K 行的 sproc 之前禁用它们。
我的问题是整个操作都存在于事务中。sproc 在配置了 TransactionScopeOption.Suppress 的 TransactionScope 中执行(这与其他事物一起运行,每个事物都会启动一个新的 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
昨晚这个过程在启动半小时后超时,回滚花了半个小时,又花了半个小时的索引重建......零工作停机时间太长...=(
更新:我已经在一个小的示例数据库上运行了该过程(并且超时很小),它不像我想象的那样。显然,该过程正在正确删除行并按照我的意愿取得进展。尽管如此,日志仍在消耗。由于我处于简单数据库模式,在这种情况下日志不应该增长吗?还是删除 sproc 如此"快",以至于我没有给实际删除行的进程保持日志清洁所需的时间?
根据您的情况,您可以使用分区视图而不是分区表。像这样:
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
如果我正确理解您的问题,您想要的是一个自动滑动窗口和分区表。