Rails 外键违规删除 has_many 依赖关系销毁
Rails Foreign Key violation deleting has_many relationships with dependent destroy
我在 Rails 4.2 模型中有一个简单的 has_many
关系:
class Owner < ActiveRecord::Base
has_many :nested_things, :inverse_of => :owner, :class_name => "Nested::Thing", :dependent => :destroy
end
class Nested::Thing < ActiveRecord::Base
belongs_to :owner, :inverse_of=>:nested_things
end
模型比这复杂得多,还有许多其他关系。
今天有人试图删除一个 Owner
,但失败了,因为 nested_things
table:
上有一个外键
> psql annoying_problem
psql (9.5.3)
Type "help" for help.
annoying_problem=# \d+ nested_things
Table "public.nested_things"
Column | Type | Modifiers | Storage | Stats target | Description
------------------+-----------------------------+----------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('nested_things_id_seq'::regclass) | plain | |
owner_id | integer | | plain | |
Indexes:
"nested_things_pkey" PRIMARY KEY, btree (id)
"ix_nested_things_on_owner_id" btree (owner_id)
Foreign-key constraints:
"nested_things_owner_id_fk" FOREIGN KEY (owner_id) REFERENCES owners(id)
删除 owner
时,这是一个耗时的过程 - 此特定记录在本地生成了所有 SQL 执行的 109,000 行日志文件。但是,nested_things 关系导致整个操作中止,因为外键检查失败。
这似乎是日志文件的相关部分:
> grep -n nested_things delete-owner.txt
....
109762: SQL (1.1ms) DELETE FROM "nested_things" WHERE "nested_things"."id" = [["id", 8665]]
109836: ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation:
ERROR: update or delete on table "owners" violates foreign key
constraint "nested_things_owner_id_fk" on table "nested_things"
109837: DETAIL: Key (id)=(6343) is still referenced from table "nested_things".
此所有者只有一个 nested_things 条目。 什么会导致 Rails 中的 :dependent => :destroy 关系删除依赖关系,但外键检查失败?
原来答案是 has_many 关系的默认范围,在销毁中没有考虑。
我在 Rails 4.2 模型中有一个简单的 has_many
关系:
class Owner < ActiveRecord::Base
has_many :nested_things, :inverse_of => :owner, :class_name => "Nested::Thing", :dependent => :destroy
end
class Nested::Thing < ActiveRecord::Base
belongs_to :owner, :inverse_of=>:nested_things
end
模型比这复杂得多,还有许多其他关系。
今天有人试图删除一个 Owner
,但失败了,因为 nested_things
table:
> psql annoying_problem
psql (9.5.3)
Type "help" for help.
annoying_problem=# \d+ nested_things
Table "public.nested_things"
Column | Type | Modifiers | Storage | Stats target | Description
------------------+-----------------------------+----------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('nested_things_id_seq'::regclass) | plain | |
owner_id | integer | | plain | |
Indexes:
"nested_things_pkey" PRIMARY KEY, btree (id)
"ix_nested_things_on_owner_id" btree (owner_id)
Foreign-key constraints:
"nested_things_owner_id_fk" FOREIGN KEY (owner_id) REFERENCES owners(id)
删除 owner
时,这是一个耗时的过程 - 此特定记录在本地生成了所有 SQL 执行的 109,000 行日志文件。但是,nested_things 关系导致整个操作中止,因为外键检查失败。
这似乎是日志文件的相关部分:
> grep -n nested_things delete-owner.txt
....
109762: SQL (1.1ms) DELETE FROM "nested_things" WHERE "nested_things"."id" = [["id", 8665]]
109836: ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation:
ERROR: update or delete on table "owners" violates foreign key
constraint "nested_things_owner_id_fk" on table "nested_things"
109837: DETAIL: Key (id)=(6343) is still referenced from table "nested_things".
此所有者只有一个 nested_things 条目。 什么会导致 Rails 中的 :dependent => :destroy 关系删除依赖关系,但外键检查失败?
原来答案是 has_many 关系的默认范围,在销毁中没有考虑。