Ruby on rails Rails,heroku postgres crane返回空结果集

Ruby on rails Rails,heroku postgres crane返回空结果集,ruby-on-rails,ruby,ruby-on-rails-3,heroku,heroku-postgres,Ruby On Rails,Ruby,Ruby On Rails 3,Heroku,Heroku Postgres,我们正在使用heroku作为部署服务。我们的postgres加载项计划是具有400 mb内存限制的crane,我们的数据库中有460MB数据。直到2天前,有时postgres服务器开始响应空结果集 这里有一个关于这种情况的例子 我们的条目模型和保存回调后都有一个属性,它将条目号分配给条目对象,但该条目号与对象id不同。 这是我们的回调方法 def assign_entry_no return true unless self.new_record? && !self.proj

我们正在使用heroku作为部署服务。我们的postgres加载项计划是具有400 mb内存限制的crane,我们的数据库中有460MB数据。直到2天前,有时postgres服务器开始响应空结果集

这里有一个关于这种情况的例子 我们的条目模型和保存回调后都有一个属性,它将条目号分配给条目对象,但该条目号与对象id不同。 这是我们的回调方法

def assign_entry_no
  return true unless self.new_record? && !self.project.nil?
  last_entry = Entry.where(:project_id => self.project_id).last
  self.entry_no = last_entry.nil? ? 1 : (last_entry.entry_no + 1)
end
这是输出

object_id -> id
---------|----
677467 -> 3
677466 -> 2
677465 -> 1 // empty result set
677462 -> 3
677461 -> 2
677460 -> 1 // empty result set
677459 -> 31
677458 -> 30
677457 -> 29
正如您所看到的,有时postgres服务器返回空的结果集。 我们认为,如果我们将插件计划升级到800MB,我们将解决这个问题。 以前有没有人遇到过这个问题,是关于postgres服务器还是其他问题


我们的系统=>rails 3.0.2、mri ruby 1.9.3

Heroku Postgres计划为您提供专用的缓存空间。Crane计划中的数据量可以超过400mb,但有些查询的响应速度可能较慢,因为数据库必须从磁盘访问数据

我的假设是,您的assign\u entry\u no方法没有做您认为应该做的事情

我将逐行剖析该方法,向您展示一些改进和可能遇到的问题

  return true unless self.new_record? && !self.project.nil?
这条线应该和你想的一样。但是,您可以通过将条件反转为if self.persistent?&&自我项目标识是否存在?。这将阻止您先执行除非,然后再撤消您计算机上的除非!self.project.nil?条款此外,使用project_id而不是project可以保存数据库查询

  last_entry = Entry.where(:project_id => self.project_id).last
这就是问题所在。首先,您在select上没有排序,因此最终可能会得到不一致的结果。我建议做一些类似Entry.whereproject\u id:project\u id.orderid::desc.first的事情。通过这种方式,可以在一定程度上保证将最后一个id并发问题放在一边

另一个问题是您的作用域是:project\u id。我怀疑当您创建一个新项目(比如id=44)时,您的查询是从project\u id=44 ORDER BY id DESC LIMIT 1;的条目中选择id;。因为项目44是新的,所以没有条目,所以得到一个空集。这将导致下一行将条目_no分配给1。您可能会获得唯一的[project\u id,entry\u no]集,但不会获得[entry\u no]属性。我说可能,因为在并发环境中,可能会同时创建两个条目,这两个条目在保存新条目之前都会获得相同的last_条目记录

  self.entry_no = last_entry.nil? ? 1 : (last_entry.entry_no + 1)
如果这是你打算做的,这句话似乎很好。有些人更喜欢语法self.entry\u no=if last\u entry.nil?然后1 else last_entry.entry_no+1 end,但逻辑相同

结论
如果您真的希望每个条目记录都有一个唯一的条目号,为什么不使用id列呢?它是自动递增的,并且由数据库保证是唯一的。如果您想要[project\u id,entry\u no]对的唯一性,那么您的代码通常已经做到了。运行SQL查询,从条目中选择id、项目id、条目号;你应该看看这个。如果这是您想要的,我建议您在[:project\u id,:entry\u no]上的entries表中添加一个唯一的索引,这样您就可以保证不会得到重复的条目。

当您说最后一个条目时,您的意思是要得到最新的条目吗?如果是这样,则不保证以下行提供最新的行last\u entry=entry。其中:project\u id=>self.project\u id.last。您必须按如下顺序排列结果:最后一个条目=条目。其中:project\u id=>self.project\u id.order'created\u at desc'。上次您清楚地阅读了我们的回调代码吗?如果没有记录,此代码为条目编号指定1。是的,我看到您正在处理没有记录的情况。我的观点是,当有一些记录时,查询不一定会返回最新的记录,因为您没有按时间排序。您的回答非常好,感谢您的关注。但是,我没有找到导致此问题的确切原因。当您运行SELECT project\u id、entry\u no、,按项目id、条目编号从条目组中计算*;?您应该看到每个项目id、条目号对都是唯一的,但不是每个条目号都是唯一的。