1

我有一个数据库,其中数据以某种批次进行处理,每个批次甚至可能包含一百万条记录。我正在控制台应用程序中处理数据,当我完成一个批次时,我将其标记为完成(以避免再次读取它以防它没有被删除),删除它并继续下一个批次。

我有以下简单的存储过程,它删除已处理的“批次”数据

CREATE PROCEDURE [dbo].[DeleteBatch]
(
    @BatchId bigint
)
AS

SET XACT_ABORT ON
BEGIN TRANSACTION
    DELETE FROM table1 WHERE BatchId = @BatchId
    DELETE FROM table2 WHERE BatchId = @BatchId
    DELETE FROM table3 WHERE BatchId = @BatchId
COMMIT
RETURN @@Error

我正在使用命令超时值为 10 分钟的 NHibernate,并且 DeleteBatch 过程调用偶尔会超时。

其实我不想等待 DeleteBatch 完成。我已经将该批次标记为完成,因此如果没有更多待处理的批次,我想继续处理下一个批次,或者甚至退出我的控制台应用程序。

我正在使用 Microsoft SQL Express 2012。

是否有任何简单的解决方案可以告诉 SQL 服务器 - “启动 DeleteBatch 并异步运行它,即使我断开连接,我什至不需要过程的结果”?

如果我可以为 DeleteBatch 设置较低的处理优先级,那就太好了,因为其他查询比 DeleteBatch 更重要。

4

6 回答 6

3

我不太了解NHibernate。但是,如果您曾经或可以在这种情况下使用 ADO.NET,那么您可以使用C# 中的SqlCommand.BeginExecuteNonQuery方法轻松实现异步数据库操作。此方法启动异步执行不返回行的 Transact-SQL 语句或存储过程的过程,以便在执行该语句时其他任务可以同时运行。

编辑:如果您真的想在 db 操作结束之前退出控制台应用程序,那么您将不得不在代码中手动创建线程并在这些线程中执行 db 操作。现在,当您关闭控制台应用程序时,这些线程仍然存在,因为使用 System.Thread.Thread 创建的线程默认是前台线程。但话虽如此,考虑将创建多少线程也很重要。在您的情况下,您必须为每批分配 1 个线程。如果批次数量非常大,则需要创建大量线程,这反过来会占用大量 CPU 资源,甚至会长时间冻结您的操作系统。

我可以建议的另一个简单解决方案是将 BatchIds 插入到某个数据库表中。INSERT TRIGGER在该表上创建一个。然后,此触发器将调用一个以 BatchId 作为其参数的存储过程,并执行所需的任务。
希望能帮助到你。

于 2012-09-14T10:13:58.960 回答
1

如果您的控制台应用程序不是尝试删除批处理,而是将批处理 id 写入“BatchIdsToDelete”表,该怎么办。然后,您可以使用每 x 分钟/秒或其他任何时间运行的代理作业来删除给定批次 id 的前 x% 记录,并且可能在处理下一个 x% 之前先睡一会儿。也许值得一看?

于 2012-09-14T09:40:51.873 回答
1

聚会迟到了,但如果其他人有这个问题,请使用SQLCMD. 使用 express 时,您的用户数量是有限的(我认为是 2,但自从我上次使用 express 做很多事情以来,它可能已经改变了)。您可以拥有sqlcmd、运行查询、存储过程...

您可以sqlcmd使用 Windows Scheduler 启动。一个脚本,一个前景规则......

我用它来管理大约 3 或 4000 个 SQL Server Express 实例,并使用 Windows 调度程序安排它们的夜间维护。

您还可以创建和运行 PowerShell 脚本,它比sqlcmd.

于 2018-11-08T22:30:56.133 回答
0

I needed a same thing..

After searching for long time I found the solution Its d easiest way

        SqlConnection connection = new SqlConnection();
            connection.ConnectionString = "your connection string";

            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connection.ConnectionString);
            builder.AsynchronousProcessing = true;

            SqlConnection newSqlConn = new SqlConnection(builder.ConnectionString);

            newSqlConn.Open();
    SqlCommand cmd = new SqlCommand(storeProcedureName, newSqlConn);

            cmd.CommandType = CommandType.StoredProcedure;
    cmd.BeginExecuteNonQuery(null, null);
于 2013-02-21T11:07:11.280 回答
0

查看这篇文章,它解释了如何进行可靠的异步过程执行,包括代码。IS 基于服务代理。

尝试使用 .NEt 异步功能(如 BeginExecute 或任务等)的问题在于调用不可靠:如果进程在过程完成之前退出,则由于会话断开,服务器中的执行将被取消。

但是你还需要看任务本身,为什么删除需要+10分钟?它被争用阻止了吗?你缺少索引BatchId吗?使用性能故障排除流程图

于 2012-09-14T12:56:42.370 回答
0

理想情况下,SQLConnection 对象应采用可选参数/属性、Web 服务的 URL、WCF 或 WebApi 或尚未命名的东西,如果用户愿意,通过调用此函数通知用户执行进度和/或完成状态带有众所周知的消息的 URL。

理论上 DBConnection 是一个可以自由实现的可扩展对象。但是,在可以说这种方法可行之前,需要对真正可以做和需要做的事情进行一些审查。

于 2017-03-09T16:50:42.880 回答