If I concurrently run 100 times this. What will I get key1 == 100 or key1 = 1? If 100, why?
db.transaction(trx => {
k1 = trx.read('key1) || 0
trx.write('key1',k1++)
})
If I concurrently run 100 times this. What will I get key1 == 100 or key1 = 1? If 100, why?
db.transaction(trx => {
k1 = trx.read('key1) || 0
trx.write('key1',k1++)
})
Did you mean ++k1
instead of k1++
?
Assuming this is using the default retry loop, after all 100 transactions commit you will see key1 >= 100. This is because the default retry loop assumes transactions are idempotent, so it retries commit_unknown_result
. It could be that there was a network fault after attempting to commit one of these transactions and before getting a reply, but the attempt actually succeeded and the retry would increment a second time.
You would also see a lot of retries because of not_committed
errors, since by default transactions don’t commit if any of the reads they performed might have given a different result at commit time. Each of the 100 transactions will commit one at a time and see the writes from all previously committed transactions.
Thanks Andrew,
It could be that there was a network fault after attempting to commit one of these transactions and before getting a reply, but the attempt actually succeeded and the retry would increment a second time.
What is best practice to mitigate such effects (except indempotence)?
There’s some advice here: Developer Guide — FoundationDB 6.3. There’s also some discussion on handling this automatically here: Automatically providing transaction idempotency, but I don’t think anyone is actively working on this.