数据存储会生成覆盖我实体的ID吗?

1 投票
3 回答
644 浏览
提问于 2025-04-18 12:21

我有一个根实体类型,想把它改造成有父实体的结构。

这些实体的ID是自动分配的。

我把所有现有的实体复制了一遍,新的实体的键是由父实体和旧实体的ID组合而成的。然后我删除了旧的实体。

任何新创建的实体都会从数据存储中自动分配ID。

文档上说:

数据存储的自动ID分配器不会把一个已经存在的实体的键分配给新的实体。

...但我不确定这是否只适用于预先分配的ID。

我新创建的实体会不会覆盖掉已经存在的实体?或者数据存储会不会因为父实体不同而仍然识别这些ID已经被使用过了?

我是否需要预先分配我所有现有实体的ID,以防止新实体覆盖旧实体?

编辑:

我的旧实体的键是这样的:

datastore_types.Key.from_path(u'MyKind', 123456789, _app=u's~my-app')

而我新的克隆实体的键是这样的(重用了旧的ID): datastore_types.Key.from_path(u'ParentKind', 28882914L, u'MyKind', 123456789, _app=u's~my-app')

所以数据存储会不会认为这个ID已经被这个类型使用过,尽管父实体不同?

3 个回答

0

根据对 allocate_id_range 的各种可能返回值的描述,我们可以放心地说,当使用自动ID分配器时,数据存储不会用一个新实体覆盖掉已经存在的实体。

根据SDK的说明:

KEY_RANGE_EMPTY = "Empty"
"""Indicates the given key range is empty and the datastore's
automatic ID allocator will not assign keys in this range to new
entities.
"""

KEY_RANGE_CONTENTION = "Contention"
"""Indicates the given key range is empty but the datastore's
automatic ID allocator may assign new entities keys in this range.
However it is safe to manually assign keys in this range
if either of the following is true:

 - No other request will insert entities with the same kind and parent
   as the given key range until all entities with manually assigned
   keys from this range have been written.
 - Overwriting entities written by other requests with the same kind
   and parent as the given key range is acceptable.

The datastore's automatic ID allocator will not assign a key to a new
entity that will overwrite an existing entity, so once the range is
populated there will no longer be any contention.
"""

KEY_RANGE_COLLISION = "Collision"
"""Indicates that entities with keys inside the given key range
already exist and writing to this range will overwrite those entities.
Additionally the implications of KEY_RANGE_COLLISION apply. If
overwriting entities that exist in this range is acceptable it is safe
to use the given range.

The datastore's automatic ID allocator will never assign a key to
a new entity that will overwrite an existing entity so entities
written by the user to this range will never be overwritten by
an entity with an automatically assigned key.
"""

另外一个StackOverflow的回答也同意这个观点:AppEngine allocateIdRange : 关于竞争状态的澄清

0

如果我理解没错的话,旧的实体会有之前的ID加上父级ID,对吧?新的实体也会有父级ID。在这种情况下,Datastore不会覆盖任何实体,因为它从来不会分配重复的键。

1

数据存储系统不会认为这个 ID 已经被使用。当数据存储系统分配 ID 时,它是根据类型和父级来分配的(具体可以查看这个 链接)。因为你新创建的模型有不同的父级,所以它们会从自己的 ID 序列中分配,这可能会和你手动设置的 ID 冲突。

自动生成的 ID 只保证不会和其他自动生成的 ID 冲突(比如使用 put 方法时没有设置 ID,或者使用 allocate_ids 方法)。

撰写回答