我们注意到我们数据库中的各种表格都出现了很多重复记录,但是不知道为什么会这样。有趣的是,虽然记录本身是重复的(包括
created_at
时间戳),但是在我们的用户表中,每个记录的密码盐和哈希值都不同,这让我相信Rails在某些情况下会运行两次事务/保存操作。显而易见的是,我们在应用程序代码中没有多次调用save
或create
。
并不是每个保存在数据库中的记录都会出现这种复制现象,我们还无法推断出模式。在用户模型上还有一个validates_uniqueness_of
验证(尽管表格上没有唯一键;我们需要清除所有重复记录才能做到这一点)--因此,如果记录已经存在,Rails应该停止插入,但是如果请求同时发生,那么就是竞态条件。
目前我们正在使用Passenger 3.0.11/nginx在我们的应用服务器(目前有2台)后面运行Rails 3.2.2,并且有一个中央nginx web服务器,将请求发送到一个应用服务器。这种设置会导致进程被复制或者其他的问题吗?请求没有锁定到一个上游服务器上,是否会有影响?(例如,如果一个用户请求包括静态内容(如图像)的页面,则可能使用一个或两个应用服务器)?(我觉得这是在抓住稻草,但我想覆盖每个可能性)
还有什么其他原因会导致这种情况发生?
更新:例如,今天创建了一个用户,它得到了重复记录。两个记录都有created_at
时间戳为“2012-03-28 16:48:11”,除hashed_password
和salt
以外的所有列都相同。从请求日志中可以看到以下内容:
应用服务器1:
Started POST "/en/apply/create_user" for 1.2.3.4 at 2012-03-28 12:47:19 -0400
[2012-03-28 12:47:19] INFO : Processing by ApplyController#create_user as HTML
[2012-03-28 12:47:20] INFO : Rendered apply/new_user.html.erb within layouts/template (192.8ms)
Started POST "/en/apply/create_user" for 1.2.3.4 at 2012-03-28 12:48:10 -0400
[2012-03-28 12:48:10] INFO : Processing by ApplyController#create_user as HTML
[2012-03-28 12:48:11] INFO : Redirected to apply/initialize_job_application/3517
[2012-03-28 12:48:11] INFO : /app/controllers/apply_controller.rb:263:in `block (2 levels) in create_user'
应用服务器2:
Started POST "/en/apply/create_user" for 1.2.3.4 at 2012-03-28 12:48:10 -0400
[2012-03-28 12:48:10] INFO : Processing by ApplyController#create_user as HTML
Web服务器:
1.2.3.4 - - [28/Mar/2012:12:48:10 -0400] "POST /en/apply/create_user HTTP/1.1" 499 0 "en/apply/create_user" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)" "-"
1.2.3.4 - - [28/Mar/2012:12:48:11 -0400] "POST /en/apply/create_user HTTP/1.1" 302 147 "en/apply/create_user" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)" "-"
因此,创建操作被触发了三次(第一次由于错误返回到表单,可能是这个原因),并且每个服务器至少执行了一次。后两个都被Web服务器注册为单独的请求,但第一个获得状态代码499 Client Closed Request
(根据维基百科是Nginx的扩展),而第二个得到了预期的302
。这里的499是否会导致问题?