Rails:创建时违反约束但更新时不违反约束

3
注意: 这是一个更加简洁的“railsier”版本,与this question相比,后者有点冗长。

我在生产服务器上得到了Rails行为,但在开发服务器上无法复制。 代码库除了凭据和缓存设置外完全相同,两个服务器都由Oracle 10g数据库提供支持,具有相同的模式(但不同的数据)。

我的Rails应用程序包含一个用户模型,其中包含一个注册; 注册又通过registration_ownerships表与company_ownerships进行has_and_belongs_to_many关联。 用户注册后,填写与所有三个模型相关的数据,包括一系列复选框,指示哪些registration_ownerships可能适用于他们的帐户。

在开发服务器上,无论输入什么数据,注册过程都是无缝的。但是在生产环境中,如果用户在提交注册之前勾选了任何公司所有权字段,Oracle 就会抱怨 company_ownerships 表的主键(基于 company_ownership_id 和 registration_id 的两个字段键)违反了约束条件,用户将看到标准的 Rails 500 错误屏幕。在每种情况下,我都已经验证了生产数据库中不存在这两个字段的任何冲突记录,所以我不知道为什么违反了约束条件。
更让事情混乱的是,如果用户在注册时没有列出任何所有权,并且稍后返回并修改其帐户以反映所有权数据(通过相同的界面完成),则应用程序将满足他们的请求,Oracle 表现良好(这在生产和 dev 上都是如此)。
我花了过去几天时间试图弄清楚可能导致这个问题的原因,现在已经到了无法解决的地步。非常感谢任何建议!
更新日期为 4/15/10:我刚刚注意到一些可能有用的东西。我尝试在 dev 和 production 上注册相同的账户,并故意将“电话”字段留空,这是一个必填字段。在 dev 上,我收到了以下消息:

1个错误阻止了此注册的保存

以下字段存在问题:

  • 电话不能为空

然而,在生产环境中,我得到了这个:

2个错误阻止了此注册的保存

以下字段存在问题:

  • 电话不能为空
  • 电话不能为空

我猜想这直接与生产环境中违反的约束条件有关——也许作为提交的一部分,该字段被插入了一次,然后第二次插入时违反了约束条件,然后回滚了整个事务,删除了最初插入的所有证据。有没有关于可能导致这种行为的想法,无论是在Rails端还是在Oracle端?

2个回答

1
首先,检查应用程序是否连接到您认为它连接的数据库。
其次,检查数据类型,包括数字精度。例如,在以下示例中,小数位数被静默地截断,因此第二个插入将由于重复键而失败。
create table test_pk (pk_1 number(3,0), pk_2 number(3,0), val varchar2(20));
alter table test_pk add constraint test_pk_pk primary key (pk_1, pk_2);
insert into test_pk values (10.1, 10.1, 'test 10.1');
insert into test_pk values (10.2, 10.2, 'test 10.2');

最坏的情况是禁用约束条件,尝试操作,然后重新启用约束条件。这将告诉您是否真的存在一些重复数据。可能会出现一些奇怪的竞争条件,涉及连接池和非立即操作(例如,在连接a中插入,在连接b中删除,在连接a中再次插入,然后在连接b提交之前)。

0
恰好,在目录中有一个“registrations”模型的备用副本;即使它有不同的名称(例如“registrations_2349871.rb”),Rails也会运行所有模型功能(保存、验证等)两次,因此导致了关键约束冲突!我以前从未见过这样的行为。删除这个问题文件解决了问题。

你真的应该分析一下那个文件是如何进入生产环境并通过您的审核和部署流程的。存在错误代码,没错。但错误的代码文件?那就有点过了。 - Dan Rosenstark
完全同意。可以说,这个特定项目的工作流程有点...嗯...非正统(多个开发人员之间不总是紧密沟通),而且这不是我们第一次被咬到。希望这是最后一次... - justinbach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接