我正在创建一个Twitter应用程序,每次用户更新页面时,它都会重新加载来自Twitter的最新消息并将它们保存到本地数据库,除非它们之前已经创建过.这在开发环境(数据库:sqlite3)中运行良好,但在生产环境(mysql)中,它总是会再次创建消息,即使它们已经创建过.
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文本或任何可以帮助我找到问题的内容.
您可以通过在config/environment/production.rb中设置日志级别来更改生产中的日志级别
config.log_level = :debug
这将记录sql以及您在dev中看到的所有其他内容 - 它会使应用程序变慢,并且您的日志会很大,因此请谨慎使用.
但至于问题背后的实际问题......
可能是因为多个连接访问mysql?
如果尚未提交twitter条目,那么从另一个连接查询它们将不会返回它们,因此如果在提交之前调用它们的查询,那么您将找不到它们,而是将插入相同的条目再次.在具有许多用户的生产环境中,这比在sqlite上单独测试更有可能发生.
由于您使用的是mysql,因此您可以使用twitter id上的唯一键来防止欺骗,然后在尝试插入欺骗时捕获ActiveRecord异常.但这意味着处理错误,这不是处理这个问题的一种很好的方式(尽管我建议将其作为防止欺骗的备份方法 - mysql对此有好处,使用它).
您还应该阻止尝试插入欺骗.一种方法是在公共记录上使用锁定,比如说所有推文都与之相关的用户记录,这样另一个进程就无法尝试为用户添加推文,直到它能够获得该锁定(只有在事务已完成),因此阻止同时提交相同的信息.