集中数据库:多个消费者

时间:2011-07-07 05:12:54

标签: c# .net sql-server database network-programming

我有一个表,其中包含在本地网络中不同计算机上运行的起始数据和多个消费者应用程序。

请建议我如何设置它们以便只从该数据库中获取一次记录,因此不会出现2个或更多应用程序从表中获取相同记录的任何情况。

我看到了两种可能的方法来解决它,但不确定:

  1. 还有一个应用程序将接收来自消费者应用程序的请求,并为其提供唯一的未处理记录,
  2. 在数据库中实现一些存储过程......
  3. 请告知..

4 个答案:

答案 0 :(得分:3)

要检索行,请创建一个存储过程:

  • 启动交易
  • 选择并锁定可用的行
  • 更新该行的一列以标记其他人不可用
  • 提交交易
  • 将行传递给客户端

要更新行,请创建一个存储过程:

  • 开始交易
  • 更新行(可选择检查rowversion)
  • 更新行的可用性
  • 提交交易

附加的:

  • 您可能希望在该行中添加日期/时间,以便了解行何时被锁定
  • 如果一行已被锁定很长时间(超过您的预期),您可以释放锁定并让其他人选择该行。但是,为了防止以前的所有者更新(他不知道他丢失了锁),你应该在表中有一个rowversion列。
  • 您可以将(联合国)可用状态保存在单独的表格中,以便更容易找到可用的行。

答案 1 :(得分:1)

各种选择:

  • 使用交易并在拍摄时将每个记录标记为正在进行中;永远不要记录已经标记的记录(注意:您可能需要“取消标记”耗时太长的项目,例如机器已经死亡)
  • 使用随机排序(或许NEWID)来选择不太可能冲突的行

然而,个人有其他存储隐喻在这里运作良好,例如“redis”有一些合适的操作:

  • RPOPLPUSH(在列表之间移动1条记录,然后将其返回)
  • SPOP(随机删除并返回1条记录)
  • RPOP / LPOP(从列表末尾删除并返回1条记录)

所有这些都是原子的,避免了所有会使这成为SQL的痛苦。

答案 2 :(得分:0)

使用ProcessedBy向表中再添加一个字段,如果没有启动机器处理它,则可以将该值设置为null,如果它开始处理,则将值设置为machinename。在获取记录时,您可以验证此processedBy字段,如果它为null,则可以分配给任何计算机。

答案 3 :(得分:0)

您要求的是默认数据库行为。 您可以使用“SELECT ...... FOR UPDATE”,数据库引擎将锁定该行并使其对其他用户不可用。 但是,如果您的程序想要在很短的时间内(少于1秒)保存数据,那么这只是一个很好的做法,您的应用程序将持续数据的时间更长,会遇到很多死锁和争用问题。

您可以在应用程序代码中执行此操作,方法是使用“RESERVED_BY_USER”和“RESERVED_UNTIL”等列,应用程序可以自行管理。

然而,根据您所描述的内容,我认为您真正想要的是一个如here

所述的队列