我们注意到很多重复记录正在我们的数据库中的各种表格中创建,但是为什么会发生这种情况而不知所措。有趣的是,虽然记录是重复的(甚至是created_at
邮票!),但在我们的用户表中,每条记录上的密码salt和hash不同 - 这让我相信Rails以某种方式运行事务/保存操作两次。很明显,我们在应用程序代码中不会多次调用save
或create
。什么可能导致Rails创建重复记录?
对于保存在数据库中的每条记录,似乎都没有发生这种重复,而且我们似乎还无法推断出模式。在用户模型上还有一个validates_uniqueness_of
验证(虽然表格上还没有唯一的密钥;我们需要清理所有重复项以便能够做到这一点) - 所以如果记录已经存在,Rails应该停止自己,但是如果请求同时触发这是一种竞争条件。
我们目前在我们的应用程序服务器(当前是2个)上运行Passenger 3.0.11/nginx后面的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)" "-"
所以创建操作被击中了三次(可能是第一次由于错误返回到表单),并且每台服务器至少一次。后两者都被网络服务器注册为单独的请求,但第一个获得状态代码499 Client Closed Request
(根据维基百科的一个nginx扩展),第二个得到如预期的302
。 499会造成这里的问题吗?
你看过你的应用程序日志文件?当存在一个重复的用户在数据库中可以找到2个请求在你的日志文件对应的点或只有一个? – 2012-03-28 19:13:48
我们在生产中没有完整的rails查询日志,只有请求日志。然而,插入存在于mysql bin-log中,并且create action在请求日志中不止一次显示至少有一个例子le(尽管这可能不会导致多个*确切的重复*记录,不是?) – 2012-03-28 19:22:15
但是,你能看到匹配te重复记录或只有单个请求的请求对吗? – 2012-03-28 19:25:06