2010-01-16 155 views
2

我正在创建一个Twitter应用程序,并且每次用户更新页面时,它都会从Twitter重新加载最新消息并将它们保存到本地数据库,除非它们之前已经创建。这在开发环境(数据库:sqlite3)中运行良好,但在生产环境(mysql)中,它总是再次创建消息,即使它们已经被创建。Rails在生产环境中调试

消息创建由twitter_id检查,每个消息有:

msg = Message.find_by_twitter_id(message_hash['id'].to_i) 
if msg.nil? 
    # creates new message from message_hash (and possibly new user too) 
end 
msg.save 

显然,在生产环境中是无法找到的Twitter ID消息由于某些原因(当我看着它保存在数据库所有的属性都正确)。

有了这么长的介绍,我想我的主要问题是如何调试呢? (除非你已经有一个答案的主要问题,当然:)当我看在production.log,那只能说明是这样的:

Processing MainPageController#feeds (for 91.154.7.200 at 2010-01-16 14:35:36) [GET] 
Rendering template within layouts/application 
Rendering main_page/feeds 
Completed in 9774ms (View: 164, DB: 874) | 200 OK [http://www.tweets.vidious.net/] 

...但不是数据库的请求,logger.debug文字,或任何可以帮助我找到问题的东西。

+1

为什么不在开发中使用MySQL,出于兴趣? – 2010-01-16 15:17:41

+0

消息散列由什么组成? – Eimantas 2010-01-16 15:18:49

+0

John,sqlite3默认为...但是,在开发和生产中使用相同的数据库可能会更容易。 – JussiR 2010-01-16 15:36:43

回答

9

您可以通过设置在配置/环境的日志级别/ production.rb

config.log_level = :debug 

将登录的SQL和一切你是用来在开发中看到改变生产日志级别 - 它会减慢应用程序的速度,并且日志会很大,所以请慎重使用。

但对于这个问题背后的实际问题......

这可能是因为多个连接访问MySQL的呢?

如果twitter条目尚未提交,那么从另一个连接查询它们将不会返回它们,因此如果在提交之前调用它们的查询,那么您将找不到它们,再次插入相同的条目。在拥有许多用户的生产环境中,这比在单独测试sqlite的情况下更有可能发生。

由于您使用的是mysql,因此您可以在twitter id上使用唯一键来防止dupe,然后在尝试插入dupe时捕获ActiveRecord异常。但是这意味着处理一个错误,这不是一个很好的方法来处理这个错误(尽管我建议将它作为备份方法来防止欺骗 - mysql对此非常有用,请使用它)。

您还应该防止尝试插入模糊。一种方法是在通用记录上使用锁定,例如所有推文都与之相关的用户记录,以便另一个进程无法尝试向用户添加推文,直到获得该锁定为止(您只能在交易完成),并且因此阻止同一信息的同时提交。

+0

感谢您的调试代码。当我查看日志时,发现问题:出于某种原因,在生产/ mysql数据库中,它始终将相同的twitter_id保存到消息(2147483647),甚至没有任何消息的有效标识。不知道为什么我以前没有注意到... 其实,在production.log中它显示正确的创建消息的ID,如: [4; 36; 1mMessage Create(0.4ms)[0m [0; 1mINSERT INTO'messages'('retweets','twitter_id',...)VALUES(0,7852958107,...) ...但在数据库中,所有twitter_id:s已更改为2147483647. – JussiR 2010-01-17 13:08:59

+1

twitter ID对于列来说显然太大 - 默认情况下,MySQL会接受列的无效值并将它们截断为最接近的值。打开SQL_MODE类似'TRADITIONAL'来防止这种不正当行为。要解决这个问题,请将列更改为更大的int类型或其他。哦,是的 - 并且始终使用与生产相同的数据库服务器(和所有其他软件)来测试您的应用程序 - 这不值得做其他任何事情。 – MarkR 2010-01-17 13:20:25

+0

谢谢!这解决了问题。没有找到如何更改SQL_MODE(在myPHPAdmin中)。虽然可能有一个SQL命令来做到这一点?无论如何,问题解决了,我很高兴。 :) – JussiR 2010-01-17 18:04:20

1

我遇到了类似的问题,同时保存电子邮件到数据库,我同意安德鲁,设置日志级别调试更多的信息,究竟发生了什么。

至于实际问题,您可以尝试添加一个唯一的索引到数据库,这将防止用相同的参数保存两个项目。这就像validates_uniqueness,但在数据库级别,并且非常有效:Mysql Constraign Database Entries in Rails

例如,如果您不希望数据库中具有重复的文本主体和重复的推特ID(这意味着同一个人推送了相同的文本)的消息对象。然后,您可以添加到您的迁移:

add_index(:message, [:twitter_id, :body] , :unique => true) 

告诉Rails中的对象进行保存,它实际上是在数据库中获取之前这需要经过你的少量时间,这就是也许为什么此ID的查询没有按没有找到任何东西。

+0

谢谢,我必须看看。奇怪的是,即使我做了正常的“validates_uniqueness:twitter_id”,它仍然创建了这些消息,并给予了它们所有相同的twitter_id(如评论中对安德鲁斯答案的描述)。 ps。对不起,如果我的解释一直令人困惑,但twitter_id指的是在Twitter数据库中的消息自己的ID(所以它不是用户ID)。 – JussiR 2010-01-17 13:12:39

+0

我知道问题解决了,我很高兴,但我觉得我应该提到validates_uniqueness是可怕的 - 它不起作用,因为它的检查和实际提交之间的延迟允许模糊很容易发生。 – 2010-01-17 21:10:32

+0

很高兴知道。我需要开始使用上面显示的方法。 – JussiR 2010-01-18 11:05:10