2

我正在尝试执行下面的代码。有时它工作正常。但有时它不起作用。

@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),为什么会出现跨组事务错误?

4

4 回答 4

3

如日志中所述:“需要明确指定跨组事务”。尝试使用指定它

@db.transactional(xg=True)

代替:

@db.transactional
于 2014-07-07T14:58:54.970 回答
1

跨组事务错误是指正在使用的实体组,而不是使用的类型(此处Site)。

当它发生时,这是因为您正在尝试对具有不同父级的实体进行事务,因此将它们放在不同的实体组中。

无耻的插头:

您应该停止使用db并将代码移至ndb,尤其是因为您似乎处于开发阶段。

于 2013-04-03T00:30:28.550 回答
1

如果您在 get_by_key_name() 查询中指定 parent=None,这是否有效?

本质上,为了使用事务,事务中的所有实体必须共享同一个父对象(即您使用一个父对象进行查询,并使用相同的父对象创建一个新实体),或者您必须使用 XG 事务。您看到问题是因为您没有指定父级。

您可能需要创建人工实体来充当父母,以便做您想做的事情。

于 2013-04-03T04:21:45.047 回答
1

我遇到过同样的问题。通过单步执行客户端代码,我进行了以下两个观察:

1) 设置 (None) 的父级似乎仍表示该类型的父级,即使没有特定记录被选为该父级。
2) 您的交易也将包括所有 ReferenceProperty 属性。

因此,从理论上讲,如果您没有在至少有两个影响的任何类型上声明父级(通过省略或设置为(无)),则您应该获得跨组事务异常(因为如果您使用 A 类和 B 类,看起来您正在使用两个不同的实体组,分别用于 A 记录和 B 记录),以及任何 ReferenceProperty 属性引用的任何类型。

要解决此问题,您必须至少创建一个没有任何属性的种类,可以将其设置为所有以前的无父记录的父记录,以及它们声明的所有 ReferenceProperty 属性的父记录。

如果这还不够,则为跨组事务设置标志。

此外,对我来说,例外的文本是:“需要明确指定跨组事务”(复数“组”)。我有 Python AppEngine 客户端的 1.7.6 版。

如果它适合您的场景,请投票赞成这个答案。

于 2013-04-09T14:10:33.907 回答