多线程& db记录锁

时间:2009-07-31 19:04:52

标签: sql sql-server c#-2.0 bulk

需要帮助大时间....

我需要创建一个.net应用程序,它将在表格中执行一些批量操作,比如大约2,000,000条记录。有一个机会窗口,应用程序应该运行并尝试处理尽可能多的行。我在想,如果我可以拥有应用程序的多个线程,那么一次只需要记录2000条记录。处理它们,它应该能够处理更多。但是,在数据库服务器上这将是非常昂贵的。据我所知,数据库服务器是一台强大的机器,应该能够承受压力。

此外,通过一次只获取2000行,如果应用程序在处理过程中终止,它将知道再次拾取的位置。

所以,我想我要问的是......

1)我如何让应用程序选择行和&锁定那些行,以便它不会被分配给另一个线程?

2)什么样的智能可以编程到应用程序中,以便它能够从最后一次停止的地方获取处理?

由于

KP

3 个答案:

答案 0 :(得分:1)

您应该使用SQL Server Integration Services(SSIS)执行此操作,而不是重新发明轮子。它针对这些场景进行了高度优化,尤其是在2008版本中。

答案 1 :(得分:1)

我同意约翰的看法,SSIS在这种情况下有很多内置智能,可能是投入时间的最佳选择。

通过分区数据来记录此类问题。我不是在讨论物理存储分区(即添加表分区),而是逻辑处理分区。你划分你的2密耳。 N分区中的记录,基于您可以在数据访问级别利用的标准,例如。索引列,然后分配N个处理器,这些处理器在其自己的分区上开始搅拌。我们的想法是在尝试访问相同的行时不要让处理器重叠。 “处理器”可以是线程,或者更好的是ThreadPool将使用异步数据库访问方法的工作项排队。

最大的问题是很多时候你没有合适的分区键。在这种情况下,您可以像这样进行临时分区:

with cte as (
   select top (@batchSize) *
   from myTable with (rowlock, updlock, readpast)
   where <record is ready to be processed>)
update cte
   set <mark record processing>
output inserted.*

技巧是select中使用的锁定提示:通过强制和updlock锁定记录以供当前处理器处理。通过添加readpast提示,每个处理器将跳过已被其他处理器锁定的记录。这样,无论处理是什么,每个处理器都会获得自己的@batchSize批处理记录。

重要的是要了解所有这些注释都适用于涉及数据库之外的处理,例如进行Web服务调用,打印纸条或任何类似的内容。如果处理完全在数据库中,那么您应该将其表示为单个T-SQL更新,并让查询优化器在其认为合适时使用并行查询。

答案 2 :(得分:0)

我会这样做:

  • 设置一个表(最初为空)以保存主行的PK。称之为PKs_Done_Table
  • 一个帖子“从pk不在的表中选择blah(从PKs_done_Table中选择pk)
  • 同一个线程从此选择中抓取行(或行块 - 使用NTILE或多个读取)并将它们移交给其他线程进行实际处理。

处理线程:

  • 接受行/行块
  • 开始交易
  • 做的工作
  • 将已完成作品的pks插入PKs_done_table
  • 提交交易。

这应该允许您大吞吐量和安全重启,前提是您可以在任何时候对某些表进行未处理。如果情况并非如此,那么无论如何重启都是没有意义的。