Транзакции TokuMX MVCC на Java
Как сохраняются записи с высокой конкуренцией при выполнении параллельных транзакций в одном и том же документе (ах)?
Похоже, что это происходит:
- MVCC Транзакция A начинается.
- MVCC Транзакция B начинается.
- Транзакция A обновляет docA и docB.
- Транзакция А совершает.
- Транзакция B обновляет docA и docC - блокировки получены, поскольку транзакция A зафиксировала и не удерживает блокировки.
- Транзакция B фиксирует перезапись работы перехода A, выполненной в docA.
Вот пример кода:
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);
Можно ли выполнить проверку, чтобы решить, следует ли совершать транзакцию? Или это предполагаемое поведение TokuMX (или я делаю что-то не так)?
1 ответ
Многоуровневые транзакции TokuMX очень похожи на многооператорные транзакции MySQL. В вашем примере блокировка на уровне документа будет удерживаться, пока происходит обновление, поэтому обновления этой записи будут сериализованы.
Если существует конфликт, потому что две транзакции обновляют один и тот же документ одновременно, метод update возвращает ошибку, которая говорит о наличии конфликта блокировок.
Чтобы помочь вам понять, что происходит, запустите два потока, но не выполняйте ни один из них. Вы увидите, что один поток ожидает и в конечном итоге истекает с ошибкой таймаута блокировки.
Кроме того, если ваша транзакция представляет собой одно обновление, вы можете просто запустить его, вам не нужно заключать его в транзакцию. Если вы хотите использовать транзакцию, состоящую из нескольких операторов, вам может потребоваться "сериализуемая" изоляция, а не MVCC, если вы будете выполнять чтение как часть транзакции: http://docs.tokutek.com/tokumx/tokumx-transactions.html Также вам нужно зарезервировать соединение для транзакции, или пул соединений может заставить ваши транзакции вести себя ненадлежащим образом: http://docs.tokutek.com/tokumx/tokumx-transactions.html