微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PHP SilverStripe ORM:重复键值违反DataObject写入的唯一约束

我的网站上有一个函数可以很快地将一堆值保存到同一个DataObject类型中.大部分时间都可以,但偶尔我会收到错误

ERROR: duplicate key value violates unique constraint …

阅读文档,我看到:

SilverStripe does not use the database‘s built-in auto-numbering system. Instead, it will generate a new ID by adding 1 to the current maximum ID

以前查看代码看起来它从主键检索最大数量,插入带有该ID的记录,然后设置DataObject的值并再次写入.在我的负载平衡环境中,当发送这些多个条目时,我认为插入是使用相同的主键发生的,因此是错误.

据我所知,这是一个我无法解决的问题.从其他questions和doco我无法设置复合主键.我唯一能想到的是为使用DB内置自动编号系统的create运行自定义sql.

有没有更好的方法来处理此错误或我可以设置复合主键的方法

编辑

完整的错误

Query Failed: ERROR: duplicate key value violates unique constraint 'TABLE_pkey'
DETAIL: Key ('ID')=(136) already exists.

声明:

INSERT INTO "TABLE" ("ClassName", "Name", "MemberID", "OtherTabeID", "Value", "LastEdited", "Created", "ID") VALUES ($1, $2, $3, $4, $5, $6, $7, $8),Array) 

我读这个是因为它从先前确定的值插入ID而不是依赖于DB自动增量.那是对的吗?

编辑2

查看日志,看起来INSERT首先使用Created字段完成,然后选择语句来获取ID:

SELECT last_value FROM "TABLENAME_ID_seq"

然后在保存附加细节的情况下完成更新.

我觉得这可能是一种竞争条件会导致保存到不正确的行,但不会导致我目前遇到的情况.理想情况下,任何INSERT都将具有将用于更新命令的返回“ID”.

编辑3

上面的过程与我所拥有的堆栈跟踪相反,后者显示插入包含的不仅仅是Created:

pg_query_params(Resource id #154,INSERT INTO "TABLENAME" ("ClassName", "Name", "MemberID", "OTHERTABLEID", "Value", "LastEdited", "Created", "ID") VALUES ($1, $2, $3, $4, $5, $6, $7, $8),Array) 
PostgresqlConnector.PHP:200
PostgresqlConnector->preparedQuery(INSERT INTO "TABLENAME" ("ClassName", "Name", "MemberID", "OTHERTABLEID", "Value", "LastEdited", "Created", "ID") VALUES (?, ?, ?, ?, ?, ?, ?, ?),Array,256) 
Database.PHP:143
SS_Database->{closure}(INSERT INTO "TABLENAME" ("ClassName", "Name", "MemberID", "OTHERTABLEID", "Value", "LastEdited", "Created", "ID") VALUES (?, ?, ?, ?, ?, ?, ?, ?)) 
Database.PHP:193
SS_Database->benchmarkQuery(INSERT INTO "TABLENAME" ("ClassName", "Name", "MemberID", "OTHERTABLEID", "Value", "LastEdited", "Created", "ID") VALUES (?, ?, ?, ?, ?, ?, ?, ?),Closure,Array) 
Database.PHP:146
SS_Database->preparedQuery(INSERT INTO "TABLENAME" ("ClassName", "Name", "MemberID", "OTHERTABLEID", "Value", "LastEdited", "Created", "ID") VALUES (?, ?, ?, ?, ?, ?, ?, ?),Array,256) 
DB.PHP:365
DB::prepared_query(INSERT INTO "TABLENAME" ("ClassName", "Name", "MemberID", "OTHERTABLEID", "Value", "LastEdited", "Created", "ID") VALUES (?, ?, ?, ?, ?, ?, ?, ?),Array) 
sqlExpression.PHP:121

解决方法:

文档中的说明非常过时(即使2007年的SilverStripe 2.1具有正确的行为),文档描述的方法也会导致竞争条件.

复杂性是SilverStripe使用多表继承,SilverStripe所做的是这样的情况:

>插入SiteTree表
>获取生成的ID
>使用相同的ID插入Page表(和其他表)

它也可以使用相同的ID对SiteTree表进行后续UPDATE写入.

不幸的是,这并不一定能帮助您解决问题,但它至少可以解决问题的一个可能来源.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐