如何强制正在运行的t-sql查询(完成一半)提交?

如何强制正在运行的t-sql查询(完成一半)提交?,sql,sql-server,Sql,Sql Server,我有Sql Server 2008 R2上的数据库。 在那个数据库上,一个关于4亿条记录的删除查询已经运行了4天,但我需要重新启动机器。我如何强制它提交到目前为止删除的内容?我想拒绝目前为止通过运行查询删除的数据。 但问题是,查询仍在运行,在服务器重新启动之前无法完成 注意:我没有为查询设置任何隔离/开始/结束事务。查询正在SSMS studio中运行 如果机器重新启动或我取消了查询,则数据库将进入恢复模式,并将在接下来的2天内恢复,然后我需要重新运行删除,这将花费我另外4天的时间 我非常感谢在

我有Sql Server 2008 R2上的数据库。 在那个数据库上,一个关于4亿条记录的删除查询已经运行了4天,但我需要重新启动机器。我如何强制它提交到目前为止删除的内容?我想拒绝目前为止通过运行查询删除的数据。 但问题是,查询仍在运行,在服务器重新启动之前无法完成

注意:我没有为查询设置任何隔离/开始/结束事务。查询正在SSMS studio中运行

如果机器重新启动或我取消了查询,则数据库将进入恢复模式,并将在接下来的2天内恢复,然后我需要重新运行删除,这将花费我另外4天的时间

我非常感谢在这方面的任何建议/帮助或指导。 我是sql server的新手用户

提前谢谢
关于

无法阻止SQL Server尝试将数据库置于事务一致状态。每一条语句都隐含着一个事务本身(如果不是外部事务的一部分的话),并且要么执行全部,要么不执行任何操作。因此,如果取消查询或断开或重新启动服务器,SQL server将从事务日志将原始值写回更新的数据页

下次一次删除这么多行时,不要一次删除。将作业分成更小的块(我总是使用5.000作为一个神奇的数字,这意味着我在循环中一次删除5000行),以最小化事务日志的使用和锁定

set rowcount 5000
delete table
while @@rowcount = 5000
    delete table
set rowcount 0

如果要删除那么多行,则使用truncate可能会更好。Truncate非常有效地删除表中的所有行。但是,我假设您希望保留表中的一些记录。下面的存储过程备份要保存到临时表中的数据,然后截断并重新插入保存的记录。这可以很快地清理一张大桌子

请注意,truncate不能很好地处理外键约束,因此您可能需要删除这些约束,然后在清理后重新创建它们

CREATE PROCEDURE [dbo].[deleteTableFast] ( 
@TableName VARCHAR(100),
@WhereClause varchar(1000)) 
AS 
BEGIN
-- input:
-- table name: is the table to use
-- where clause: is the where clause of the records to KEEP

declare @tempTableName varchar(100);
set @tempTableName = @tableName+'_temp_to_truncate';

-- error checking
if exists (SELECT [Table_Name] FROM Information_Schema.COLUMNS WHERE [TABLE_NAME] =(@tempTableName)) begin
print 'ERROR: already temp table ... exiting'
return
end
if not exists (SELECT [Table_Name] FROM Information_Schema.COLUMNS WHERE [TABLE_NAME] =(@TableName)) begin
print 'ERROR: table does not exist ... exiting'
return
end

-- save wanted records via a temp table to be able to truncate
exec ('select * into '+@tempTableName+' from '+@TableName+' WHERE '+@WhereClause);
exec ('truncate table '+@TableName);
exec ('insert into '+@TableName+' select * from '+@tempTableName);
exec ('drop table '+@tempTableName);

end
GO
在理解数据库为何进入恢复模式之前,必须先了解D(耐久性)

一般来说,如果可能的话,应该避免长时间运行SQL。长时间运行的SQL意味着更多的资源锁定时间、更大的事务日志以及失败时的巨大回滚时间

考虑在某个id或时间分配任务。例如,若要将大容量数据从TableRC插入TableTarget,可以编写如下查询

DECLARE @BATCHCOUNT INT = 1000;
DECLARE @Id INT = 0;
DECLARE @Max = ...;
WHILE Id < @Max
BEGIN
    INSERT INTO TableTarget
    FROM TableSrc
    WHERE PrimaryKey >= @Id AND @PrimaryKey < @Id + @BatchCount;
    SET @Id = @Id + @BatchCount;
END
DECLARE@BATCHCOUNT INT=1000;
声明@Id INT=0;
声明@Max=。。。;
而Id<@Max
开始
插入到TableTarget中
来自TableSrc
其中PrimaryKey>=@Id和@PrimaryKey<@Id+@BatchCount;
设置@Id=@Id+@BatchCount;
结束

它的代码更多,更容易出错。但这是我所知道的处理海量数据的唯一方法。

感谢Dean的评论。我想补充的另一个信息是:我的数据库处于简单恢复模式,这没有什么区别。我用一个scipt更新了答案,它显示了如何删除5000×5000行。@user3380585您可能会发现,更改为大容量日志模式以运行delete语句也会提高性能,但在生产系统上不要这样做,除非是在停机期间。如果需要删除整个表,不希望事务记录,请考虑使用<代码>截断表< /C>命令。不过,删除4亿行实际上并没有那么多。我想知道是否还有其他事情发生,交易被阻止了。你能告诉我如何分块运行查询吗。我正在尝试根据MyKey删除重复记录。如何使用cte调整此选项(选择[ID]、[F2]、[F3]、[F8]、[F14]、[F29]、[F31]、[F43]、[F44]、[F45]、[F46]、[F47]、[F48]、[F49]、[F50]、[F52]、[F53]、[F54]、[F56]、[F57]、[F58]、[F59]、[F63],row_number()(按MyKey划分,按MyKey排序)作为[rn]从[myDB].[dbo].[myTable])删除cte,其中[rn]>1“@BaconBits将恢复模型从简单更改为大容量不会有任何帮助。不幸的是,这是一个很好的问题,没有很好的答案。令人惊讶的是,2014年批量DML仍然麻烦重重。