如何在没有事务的情况下执行 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 如此"快",以至于我没有给实际删除行的进程保持日志清洁所需的时间?

如何在没有事务的情况下执行 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

如果我正确理解您的问题,您想要的是一个自动滑动窗口和分区表。