Транзакции TokuMX MVCC на Java

Как сохраняются записи с высокой конкуренцией при выполнении параллельных транзакций в одном и том же документе (ах)?

Похоже, что это происходит:

  1. MVCC Транзакция A начинается.
  2. MVCC Транзакция B начинается.
  3. Транзакция A обновляет docA и docB.
  4. Транзакция А совершает.
  5. Транзакция B обновляет docA и docC - блокировки получены, поскольку транзакция A зафиксировала и не удерживает блокировки.
  6. Транзакция 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

Другие вопросы по тегам