没有事务时 GAE 上的 TransactionFailedError
TransactionFailedError on GAE when no transaction
我收到这个错误:
TransactionFailedError: too much contention on these datastore entities. please try again.
即使我没有进行任何交易。导致错误的代码行是
ndb.put_multi(entity_list) # entity_list is a list of 100 entities
这个错误不常发生所以没什么大不了的,但我很好奇为什么会出现这个错误。有什么想法吗?
这里是大部分回溯:
Traceback (most recent call last):
...
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 318, in post
self.run_from_request()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 313, in run_from_request
run(self.request.body)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 155, in run
return func(*args, **kwds)
File "/base/data/home/apps/s~opavote/2017-09-15.404125237783169549/tasks.py", line 70, in start_election
models.Voter.create(e.eid, chunk)
File "/base/data/home/apps/s~opavote/2017-09-15.404125237783169549/models.py", line 2426, in create
ndb.put_multi(voters + vbs)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3958, in put_multi
for future in put_multi_async(entities, **ctx_options)]
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
self.check_success()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 427, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 824, in put
key = yield self._put_batcher.add(entity, options)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 427, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 358, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 513, in _on_rpc_completion
result = rpc.get_result()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 928, in get_result
result = rpc.get_result()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1893, in __put_hook
self.check_rpc_success(rpc)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1385, in check_rpc_success
raise _ToDatastoreError(err)
TransactionFailedError: too much contention on these datastore entities. please try again.
请注意,错误实际上是从数据存储本身收到的,在 RPC 响应中:self.check_rpc_success(rpc)
。
这让我怀疑在数据存储方面,为了确保跨支持它的冗余基础设施的操作 consistency/reliability,每个写操作实际上都使用 same/similar 机制作为事务操作。不同之处在于,那些在客户端也有一些事务检查,before/after RPC 交换和数据存储的显式 RPC 事务 start/end 触发器。
来自 Life of a Datastore Write 的引述表明,无论操作是否为事务性的,都在使用一些通用机制(强调我的):
If the commit phase has succeeded but the apply phase failed, the
datastore will roll forward to apply the changes to indexes under two
circumstances:
- The next time you execute a read or write or start a transaction on this entity group, the datastore will first roll
forward and fully apply this committed but unapplied write, based on
the data in the log.
失败的可能原因之一就是对相同实体的并行访问过多,即使它们只是只读的。请参阅 ,尽管在那种情况下它们用于客户端的事务。
请注意,这只是一个理论 ;)
可能值得重新审查 transactions and entity groups,注意各种定义和限制。
放置 "Every attempt to create, update, or delete an entity takes place in the context of a transaction," 和 "There is a write throughput limit of about one transaction per second within a single entity group," 可能说明您所看到的内容,特别是如果 entity_list
包含属于同一实体组的实体。
我收到这个错误:
TransactionFailedError: too much contention on these datastore entities. please try again.
即使我没有进行任何交易。导致错误的代码行是
ndb.put_multi(entity_list) # entity_list is a list of 100 entities
这个错误不常发生所以没什么大不了的,但我很好奇为什么会出现这个错误。有什么想法吗?
这里是大部分回溯:
Traceback (most recent call last):
...
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 318, in post
self.run_from_request()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 313, in run_from_request
run(self.request.body)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/deferred/deferred.py", line 155, in run
return func(*args, **kwds)
File "/base/data/home/apps/s~opavote/2017-09-15.404125237783169549/tasks.py", line 70, in start_election
models.Voter.create(e.eid, chunk)
File "/base/data/home/apps/s~opavote/2017-09-15.404125237783169549/models.py", line 2426, in create
ndb.put_multi(voters + vbs)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3958, in put_multi
for future in put_multi_async(entities, **ctx_options)]
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 383, in get_result
self.check_success()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 427, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 824, in put
key = yield self._put_batcher.add(entity, options)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 427, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 358, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 513, in _on_rpc_completion
result = rpc.get_result()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 928, in get_result
result = rpc.get_result()
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1893, in __put_hook
self.check_rpc_success(rpc)
File "/base/data/home/runtimes/python27_experiment/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1385, in check_rpc_success
raise _ToDatastoreError(err)
TransactionFailedError: too much contention on these datastore entities. please try again.
请注意,错误实际上是从数据存储本身收到的,在 RPC 响应中:self.check_rpc_success(rpc)
。
这让我怀疑在数据存储方面,为了确保跨支持它的冗余基础设施的操作 consistency/reliability,每个写操作实际上都使用 same/similar 机制作为事务操作。不同之处在于,那些在客户端也有一些事务检查,before/after RPC 交换和数据存储的显式 RPC 事务 start/end 触发器。
来自 Life of a Datastore Write 的引述表明,无论操作是否为事务性的,都在使用一些通用机制(强调我的):
If the commit phase has succeeded but the apply phase failed, the datastore will roll forward to apply the changes to indexes under two circumstances:
- The next time you execute a read or write or start a transaction on this entity group, the datastore will first roll forward and fully apply this committed but unapplied write, based on the data in the log.
失败的可能原因之一就是对相同实体的并行访问过多,即使它们只是只读的。请参阅
请注意,这只是一个理论 ;)
可能值得重新审查 transactions and entity groups,注意各种定义和限制。
放置 "Every attempt to create, update, or delete an entity takes place in the context of a transaction," 和 "There is a write throughput limit of about one transaction per second within a single entity group," 可能说明您所看到的内容,特别是如果 entity_list
包含属于同一实体组的实体。