How are highly contended records saved when running concurrent transactions on the same document(s)?
It appears that this is happening:
Here is the example code:
mongoClient = new MongoClient( "localhost" , 27017 );
db = mongoClient.getDB("test");
collection = db.getCollection("testData");
//Create usable Mongo key from key String (i.e {_id:ObjectId("53b4477d44aef43e83c18922")})
String key = "53b4477d44aef43e83c18922";
String key2 = "53bfff9e44aedb6d98a5c578";
ObjectId keyObj = new ObjectId(key);
ObjectId keyObj2 = new ObjectId(key2);
//Set up the transaction
BasicDBObject transaction = new BasicDBObject();
transaction.append("beginTransaction", 1);
transaction.append("isolation", "mvcc");
db.command(transaction);
//Create search query
BasicDBObject query = new BasicDBObject().append("_id",keyObj);
BasicDBObject query2 = new BasicDBObject().append("_id",keyObj2);
//Create set
BasicDBObject set = new BasicDBObject();
set.append("$inc", new BasicDBObject().append("balance",50));
//Run command
collection.update(query, set);
collection.update(query2, set);
//Commit the transactions
BasicDBObject commitTransaction = new BasicDBObject();
commitTransaction.append("commitTransaction", 1);
db.command(commitTransaction);
Is there a check I can do to decide whether or not to commit the transaction? Or is this intended behaviour of TokuMX (or am I doing something wrong)?
TokuMX multi-statement transactions are very similar to MySQL multi-statement transactions. In your example, a document-level lock will be held while the update is happening, so updates to that record will be serialized.
If there is a conflict because two transactions are updating the same document at the same time, the update method will return an error that says there is a lock conflict.
To help you understand what happens, have two threads run this, but have neither commit. You will see one thread wait and eventually time out with a lock timeout error.
Also, if your transaction is a single update, you can just run it, you don't need to wrap it in a transaction. If you want to use a multi-statement transaction, you may want "serializable" isolation rather than MVCC, if you'll be doing reads as part of the transaction: http://docs.tokutek.com/tokumx/tokumx-transactions.html#tokumx-transactions-isolation-serializable Also, you will need to reserve a connection for the transaction, or the connection pool can make your transactions behave improperly: http://docs.tokutek.com/tokumx/tokumx-transactions.html#tokumx-transactions-multi-statement-drivers