Skip to content

Instantly share code, notes, and snippets.

@duongphuhiep
Last active April 23, 2020 14:09
Show Gist options
  • Save duongphuhiep/3a032a1be8a62f8c09e01a6344615cb6 to your computer and use it in GitHub Desktop.
Save duongphuhiep/3a032a1be8a62f8c09e01a6344615cb6 to your computer and use it in GitHub Desktop.
couchebase ACID and race condition?

First transaction:

trans1 = transactions.run((txnctx) -> {
    b1 = readBalance(wallet1)
    b2 = readBalance(wallet2)
    //transfer 10$ from wallet1 to wallet2
    if (b1 > 10) {
        upsert(wallet1.balance = b1-10);
        upsert(wallet2.balance = b2+10);
        txnctx.commit();
    }    
});

Couchbase ensure that both the wallet balance will be updated after the transaction, but cannot ensure the race-condition?:

Second transaction:

trans2 = transactions.run((txnctx) -> {
    b1 = readBalance(wallet1) //this is the balance before trans1.commit()
    b2 = readBalance(wallet2) //this is the balance before trans1.commit()
                              //now on other thread trans1.commit() 
    if (b1 > 10) {  //the value of b1 and b2 is outdated here
        upsert(wallet1.balance=b1-10);  // I hope there will be an optimistic-lock CAS to prevent this update
        upsert(wallet2.balance=b2+10);  
        txnctx.commit(); // I hope it will failed here
    }    
});

Third transaction:

trans3 = transactions.run((txnctx) -> {
    b1 = readBalance(wallet1) 
    if (b1 > threshold) { 
        //we know that we cannot trust b1 here, so we should not make important decision here..
        refuseLastOrder()
    }
});

we will need a lock mechanism for eg:

lock (wallet1.balance) 
{
    b1 = readBalance(wallet1) 
    if (b1 > threshold) {
        refuseLastOrder();
    }
}
unlock (wallet1.balance)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment