什么是确保写入数据库表的最佳方式(在Rails / AR中)是一个接一个地,一次一个地同步执行?

时间:2011-12-23 02:03:07

标签: mysql ruby-on-rails ruby-on-rails-3 activerecord delayed-job

我注意到在表列上使用不带UNIQUE约束的delayed_job之类的东西仍然会在DB中创建双重条目。我假设delayed_job会一个接一个地运行作业。 Rails应用程序在Apache上运行Passenger Phusion。我不确定这是否会发生这种情况,但我想确保队列中的每个项目依次持久保存到AR / DB,并且永远不会有多个写入数据库表同时发生。这可能吗?我将要处理的一些问题是什么?

更新

竞争条件的出现是因为使用AJAX API将数据发送到应用程序。应用程序收到一堆数据,每批数据被识别为一个会话ID(SID),最后,数据库的最终状态必须包括最新的最新AJAX PUT查询到API。有时候查询会在同一个SID的同一时间到达 - 所以我需要一种方法来确保它们不会同时尝试持久化,而是一个接一个地持续,或者只是最后一个被发送对API的AJAX请求。

我希望这能使我的特定用例更容易理解......

2 个答案:

答案 0 :(得分:0)

您可以使用LOCK TABLES语句锁定特定的一个或多个表。

总的来说,我认为依赖于此是糟糕的设计,并且可能导致可扩展性问题,因为您在应用程序流中造成了瓶颈。

通过进一步的解释,我很想在delayed_job使用的表中添加一些额外的列,并在其上添加唯一索引。如果(例如)您只需要为每个用户创建一个作业,则需要添加user_id列,然后执行

something.delay(:user_id => user_id).some_method

如果模式更复杂,您可能需要更多属性,例如有很多不同类型的工作,你只需要每个人一个,每种类型,但原则是相同的。你还要确保拯救ActiveRecord::RecordNotUnique并优雅地处理它。

对于非delayed_job内容,乐观锁定通常是处理并发情况之间的良好折衷,而不会减慢非并发情况。

答案 1 :(得分:0)

如果您担心/困扰/多个进程写入“相同”行 - 就像更多用户更新相同的order_header行 - 我建议您在行上设置一些标记绑定到current_user.id一旦current_user通过更新或取消编辑释放行,就会调用/ order_headers /:id / edit并再次将其删除。

你的用例(来自你的描述)似乎与我有点不同,所以我建议你把它留给数据库(如果是最新的 - 如5.1后的那样 - MySQL,你要添加一个可以执行实际更新的触发器/函数,在这里 - 您可以实现与上述建议相似的逻辑;某些标记绑定到排序的作业ID)