我正在尝试执行下面的代码。有时效果很好。但有时却不起作用。
@db.transactional
def _add_data_to_site(self, key):
site = models.Site.get_by_key_name('s:%s' % self.site_id)
if not site:
site = models.Site()
if key not in site.data:
site.data.append(key)
site.put()
memcache.delete_multi(['', ':0', ':1'], key_prefix='s%s' %
self.site_id)
我收到错误:
File "/base/data/home/apps/xxxxxxx/1-7-1.366398694339889874xxxxxxx.py", line 91, in _add_data_to_site
site.put()
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1070, in put
return datastore.Put(self._entity, **kwargs)
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 579, in Put
return PutAsync(entities, **kwargs).get_result()
File "/base/python_runtime/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 604, in get_result
return self.__get_result_hook(self)
File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1569, in __put_hook
self.check_rpc_success(rpc)
File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1224, in check_rpc_success
raise _ToDatastoreError(err)
BadRequestError: cross-group transaction need to be explicitly specified, see TransactionOptions.Builder.withXG
如果我只更改一个实体 (
models.Site
) 为什么我会收到跨组事务错误?
日志中提到:“跨组交易需要明确指定”。 尝试使用
来指定它@db.transactional(xg=True)
代替:
@db.transactional
如果您在 get_by_key_name() 查询中指定parent=None,这是否有效?
本质上,为了使用事务,事务中的所有实体必须共享相同的父实体(即,您使用一个父实体进行查询,并使用相同的父实体创建一个新实体),或者您必须使用 XG 事务。您遇到问题是因为您没有指定父级。
您可能需要创建人造实体来充当父母,以便做您想做的事情。
跨组交易错误是指正在使用的实体组,而不是所使用的类型(此处为
Site
)。
发生这种情况时,这是因为您正在尝试对具有不同父级的实体进行交易,因此将它们放入不同的实体组中。
您应该停止使用
db
并将代码移至 ndb
,特别是因为您似乎处于开发阶段。
我也有同样的问题。通过单步调试客户端代码,我得到了以下两个观察结果:
因此,理论上,如果您没有在您所影响的任何类型上声明父级(通过省略或设置为(无)),并且至少有两个(因为如果您使用类型 A 和类型 B,则看起来您正在使用两个不同的实体组(A 记录和 B 记录),以及任何 ReferenceProperty 属性引用的任何类型。
要解决此问题,您必须至少创建一种没有任何属性的类型,可以将其设置为所有先前无父记录的父记录,以及它们声明的所有 ReferenceProperty 属性的父记录。
如果这还不够,则设置跨组交易的标志。
此外,对我来说,例外的文本是:“需要明确指定跨组交易”(复数“组”)。我有版本 1.7.6 的 Python AppEngine 客户端。