This is in the appengine transaction docs...
Note: If your application receives an exception when committing a transaction, it does not always mean that the transaction failed. You can receive Timeout, TransactionFailedError, or InternalError exceptions in cases where transactions have been committed and eventually will be applied successfully...
Consider the following scenario
A
within a transaction.db.get(entity_a_key_goes_here)
within another transaction right after, or almost at the same time as step 2.None
, I create that entity by setting the key to entity_a_key_goes_here
and db.put()
it (Step 3 and this step run in the same transaction).My Question:
Is it ever possible for the transactional db.get()
operation at step 3 above to return a stale value (or not the updated value set on step 1)? Are transactional db.get()
operations guaranteed to return the freshest result even if the "weird" transaction exception occurs right before it?
The get is not really "transactional"; if a transaction only contains reads, then committing the transaction doesn't actually do anything. Executing a read in a transaction guarantees just one thing: if the value the read returned is not the most current value any more at the time that any writes in the transaction are applied, the transaction will abort and none of the writes will have happened.
So, the following sequence of events is allowed to happen:
But, this sequence of events is different:
So, with your step 4 added to the question, you are in the second sequence of events here. It's possible that the get in step 3 returns None even though the entity does exist, but it's not possible for the subsequent write to succeed in that case: the transaction is out of date and thus cannot commit. The transaction will be retried, and the second time around, the get will return the object written in step 1, which is what you wanted.
So the very short answer is: yes, it can return a stale value, but it's guaranteed that if the result was stale, a subsequent write to that entity in the same transaction will fail, so this should not actually cause a problem.
I think the result of step 3 in this situation will be a stale value. In this case, the "freshest" result may not be the entity from step 1.
My suggestion is to use memcache when retrieving values (falling back to a db.get()
call when memcache misses), and to update memcache when updating the entity. Use the entity key as the memcache key. In fact, this is how ndb works automatically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With