【问题标题】:How can a make a sproc execute without a transaction?如何在没有事务的情况下执行 sproc?
【发布时间】:2012-04-22 21:35:12
【问题描述】:

我有一个清理过程,每天需要删除表中大约 800 万行(有时更多)。此过程是用 C# 编写的,并使用 SMO 查询表索引的架构,在执行批量删除 500K 行的存储过程之前禁用它们。

我的问题是整个操作都存在于事务中。 sproc 在 TransactionScope 中执行,该 TransactionScope 配置了 TransactionScopeOption.Suppress(这与其他事物一起运行,每个都启动一个新的 TransactionScope),我认为这不会允许 Transaction,并且在 sproc 中有明确的提交点。

该过程的 C# 部分可以总结为:

        try {
            DisableIndexes(table);
            CleanTable(table);
        }
        finally {
            RebuildIndexes(table);
        }

存储过程内部有一个循环,基本上是:

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

昨晚这个进程在启动半小时后超时,用了半小时回滚,又花了半小时重建索引...对于零工作来说停机时间太长...=(

更新:我已经在一个小型示例数据库上运行了这个过程(并且有一个小的超时),它并不是我想象的那样。显然,该过程正在正确删除行并按照我的意愿取得进展。尽管如此,日志仍在消耗。由于我处于 SIMPLE 数据库模式,在这种情况下日志不应该不会增长吗?还是删除存储过程如此“快”,以至于我没有给实际删除行的过程提供保持日志清洁所需的时间?

【问题讨论】:

  • 你为什么在你的 SP 中使用 begin tran / commit??
  • 因为我想强制删除在单个事务中。我认为这是我在这里解决主要问题的遗留问题,整个存储过程在单个事务中运行......我将删除它并看看会发生什么(再次)。
  • 你用什么来执行你的 SQL Batch SqlCommand?一些数据访问框架?我们不得不责备一些事情,因为 TransactionScopeOption.Suppress 应该可以工作......但这取决于框架不会破坏它。
  • 当我使用 SMO 来禁用索引名称时,我正在使用 SMO 的 Database.ExecuteNonQuery() 来执行“EXEC dbo.CleanTable”。
  • 尝试使用其他东西来执行它。也许SMO负责“隐藏交易”。也许你也可以在你的进程中进行事务日志备份来控制日志的大小。

标签: c# sql-server performance tsql delete-row


【解决方案1】:

根据您的情况,您可以使用分区视图而不是分区表。比如:

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

【讨论】:

  • 啊哈!这很有趣……值得研究,谢谢。仍然想知道为什么在我的清理过程中日志被消耗...也许问题已经演变成另一个问题?
  • 如果你想了解更多关于事务日志的信息,我推荐这部电影:technet.microsoft.com/en-us/sqlserver/gg313762.aspx
【解决方案2】:

如果我正确理解您的问题,您需要的是 automatic sliding window 和分区表。

【讨论】:

  • 该选项不是仅在 SQL Server 企业版上可用吗?我已经放弃了,遗憾的是,我在标准版上,可能无法获得企业版。 =(
猜你喜欢
  • 1970-01-01
  • 2012-09-13
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-20
  • 1970-01-01
相关资源
最近更新 更多