2

我有一个 Ruby on Rails 应用程序,可以在本地使用 sqlite3 数据库正常工作,并且可以毫无问题地保存和检索记录。

当使用 postgresql 数据库在http://moviedata.herokuapp.com/上部署到 Heroku 时,即使看起来日志显示它们已保存,记录也不会保存。从数据库读取的记录很好,数据按预期显示。

添加记录的有尾日志为:

2012-08-21T19:51:31+00:00 app[web.1]: 
2012-08-21T19:51:31+00:00 app[web.1]: 
2012-08-21T19:51:31+00:00 app[web.1]: Started POST "/" for 50.53.6.156 at 2012-08-21 19:51:31 +0000
2012-08-21T19:51:31+00:00 app[web.1]:   Parameters: {"utf8"=>"✓", "authenticity_token"=>"+BYQLzhrfDkUVW8UaHikHpmtGHxpeQ/yF4VByHh9m1I=", "movie"=>{"title"=>"The Running Man", "description"=>"A documentary about a public execution game show.", "year"=>"1987", "genre"=>"science fiction"}, "commit"=>"Create Movie"}
2012-08-21T19:51:31+00:00 app[web.1]: Processing by MoviesController#index as HTML
2012-08-21T19:51:31+00:00 app[web.1]:   Rendered movies/index.html.erb within layouts/application (5.1ms)
2012-08-21T19:51:31+00:00 app[web.1]: Completed 200 OK in 9ms (Views: 6.7ms | ActiveRecord: 0.9ms)
2012-08-21T19:51:31+00:00 heroku[router]: POST moviedata.herokuapp.com/ dyno=web.1 queue=0 wait=0ms service=17ms status=200 bytes=3479

添加记录后,“heroku pg”命令在 postgres 数据库中显示相同数量的行 (11)。

这是我为学习 Rails 和 Heroku 平台而构建的一个简单应用程序。要重现这一点,只需访问http://moviedata.herokuapp.com/并单击“新电影”,在表单中输入一些垃圾数据,然后点击“创建电影”。记录应该被保存并显示在首页的列表中,但它没有。

为了能够写入 postgres 数据库,我是否必须打开、配置或激活某些东西?对我来说似乎很奇怪,它可以读取但不能写入。有比日志更好的故障排除方法吗?

在本地,我使用 Ruby 1.9.3、Rails、3.2.8、PostgreSQL 9.1.5、SQLite 3.7.9、Heroku Toolbelt 2.30.3。

编辑/更新:我将本地版本切换为使用 psql。在不保存记录的情况下,它也会遇到同样的问题。用户设置为 log_statement='all' 在 /var/log/postgresql/posgresql-9.1.main.log 登录显示了很多选择,但是当尝试添加记录时,日志显示数据库从未被命中。

Foreman 显示正在发布的数据,如下所示:

22:38:03 web.1     | Started POST "/" for 127.0.0.1 at 2012-08-21 22:38:02 -0700
22:38:03 web.1     | Processing by MoviesController#index as HTML
22:38:03 web.1     |   Parameters: {"utf8"=>"✓", "authenticity_token"=>"0AyxRbwl/Kgi05uI1KX8uxVUJjx9ylAA1ltdWgmunm4=", "movie"=>{"title"=>"Army of Darkness", "description"=>"A man fights the living dead using a boomstick.", "year"=>"1997", "genre"=>"horror"}, "commit"=>"Create Movie"}
22:38:03 web.1     |   Movie Load (0.8ms)  SELECT "movies".* FROM "movies" ORDER BY title
22:38:03 web.1     |   Rendered movies/index.html.erb within layouts/application (14.9ms)

失败的提交听起来确实是一个很好的解释。我还不确定如何检查驱动程序是否设置为提交或查看提交可能如何/何时失败。

这是一个非常简单的应用程序,没有负载平衡或复杂的配置,并且大部分代码是由“生成脚手架”命令生成的,但完全有可能在数据库被击中之前某处违反了某些约束。也许有一种方法可以将 Foreman(或 Rails)日志级别提高到 11?我还尝试改用瘦,并搜索了 log/ 文件夹中的日志文件,除了上面记录的内容之外,没有发现任何其他内容。

4

1 回答 1

2

这听起来很像一个事务问题,您COMMIT在工作后没有对事务进行处理,因此更改会丢失。如果您的 SQLite 驱动程序默认为在COMMIT没有显式或回滚的情况下关闭的事务COMMIT,并且您的 Pg 驱动程序默认为ROLLBACK,您将获得所描述的行为。如果 SQLite 默认默认自动提交每条语句,而 Pg 驱动程序默认打开事务,也会发生同样的情况。

这是使用同一个本地数据库进行测试的众多充分理由之一,因为您要在想要上线时部署到该数据库。

如果您使用的是普通 Pg 实例,我会告诉您启用log_statement = 'all'in postgresql.conf,重新加载 Pg 并查看日志。您不能在 Heroku 上执行此操作,但您可以使用heroku logs --ps postgres. 尝试运行ALTER USER my_heroku_user SET log_statement = 'all';、重新测试和检查日志。

或者,在本地安装 Pg。

想到的其他不太可能的可能性:

  • 您正在使用长时间运行的 SERIALIZABLE 事务进行读取,因此它们的快照永远不会更新。不太可能。
  • 对数据库对象的权限导致INSERTs、UPDATEs 等失败,并且您的应用程序忽略了由此产生的错误。再次,不太可能。
  • 您的DO INSTEAD规则不符合您的预期,或者BEFORE触发器返回NULL,因此默默地将操作变成了无操作。如果您使用 SQLite 进行测试,似乎不太可能。
  • 您正在写入与正在读取的数据库不同的数据库。在尝试从热备用集群等读取的设置中并非不可能。
于 2012-08-22T01:12:38.310 回答