Visão geral
Neste guia, você pode aprender como usar o Driver MongoDB C++ para executar transações. As transações permitem que você execute uma série de operações que não alteram nenhum dado até que a transação seja confirmada. Se qualquer operação na transação retornar um erro, o driver cancelará a transação e descartará todas as alterações de dados antes que elas se tornem visíveis.
No MongoDB, as transações são executadas dentro de sessões lógicas . Uma sessão é um agrupamento de operações de leitura ou escrita relacionadas que você pretende executar sequencialmente. As sessões permitem consistência causal para um grupo de operações em uma transação compatível com ACID, que é uma transação que atende a uma expectativa de atomicidade, consistência, isolamento e durabilidade. O MongoDB garante que os dados envolvidos em suas operações de transação permaneçam consistentes, mesmo que as operações encontrem erros inesperados.
Ao utilizar o driver C++ , você pode criar uma nova sessão a partir de uma instância do mongocxx::client. Em seguida, você pode utilizar a instância do mongocxx::client_session resultante para executar transações. Recomendamos que você reutilize seu cliente para várias sessões e transações, em vez de fazer a instância de um novo cliente a cada vez.
Aviso
Use uma mongocxx::client_session somente com o mongocxx::client que a criou. Utilizar uma client_session com um client diferente resulta em erros de operação.
Importante
As instâncias de mongocxx::client não são seguras para thread. Cada instância mongoxcc::client e suas instâncias filhas, incluindo mongocxx::client_session, devem ser usadas por um único thread por vez. Para saber mais, consulte o guia Segurança de threads e fork.
APIs de transações
O driver C++ do MongoDB fornece uma API de retorno de chamada e uma API central para gerenciar o estilo de vida da transação. Antes de iniciar uma transação, você deve chamar o método start_session() para instanciar um mongocxx::client_session. Em seguida, você pode usar uma das seguintes APIs para realizar uma transação:
API de chamada de resposta: API de alto nível que gerencia o ciclo de vida da transação e incorpora automaticamente a lógica de tratamento de erros.
API central: API de baixo nível que permite gerenciar o ciclo de vida da transação e implementar lógica personalizada de tratamento de erros.
Dica
Para saber mais sobre o tratamento de erros, consulte a seção Tratamento de erros de transação no manual do MongoDB Server .
API de retorno de chamada
Use a API de retorno de chamada para permitir que o driver C++ do MongoDB gerencie o ciclo de vida de sua transação. Para implementar essa API, chame o método with_transaction() no seu mongocxx::client_session e passe uma função de chamada de resposta especificando a sequência de operações que você deseja executar. O método with_transaction() inicia uma transação, executa a função de chamada de resposta e confirma sua transação ou encerra a transação se encontrar um erro. Se sua transação encontrar um erro TransientTransactionError ou UnknownTransactionCommitResult, o método with_transaction() executará novamente a transação.
O código a seguir usa a API de chamada de resposta para executar uma transação que insere documentos nas coleção movies e comments no banco de dados sample_mflix . Este código executa as seguintes ações:
Inicia uma sessão a partir do cliente utilizando o método
start_session().Define uma função de chamada de resposta que especifica as operações a serem executadas durante a transação.
Cria um objeto de opção para se preparar para definir a preocupação de gravação para as operações de transação. Para saber mais sobre semântica de leitura e escrita, consulte a seção Read Concern/Write Concern/Read Preference no manual do MongoDB Server .
Chama o método
with_transaction()para gerenciar a transação, passando a função de chamada de resposta e o objeto de opção como argumentos.
// Establish a connection to the MongoDB deployment mongocxx::instance instance{}; mongocxx::client client(mongocxx::uri{"<connectionString>"}); // Define database and collection variables auto db = client["sample_mflix"]; auto movies_collection = db["movies"]; auto comments_collection = db["comments"]; // Define a callback specifying the sequence of operations to perform during the transaction mongocxx::client_session::with_transaction_cb callback = [&](mongocxx::client_session* session) { // Important:: You must pass the session to the operations. movies_collection.insert_one(*session, make_document(kvp("title", "Parasite"))); comments_collection.insert_one(*session, make_document(kvp("name", "Anjali Patel"), kvp("text", "This is my new favorite movie!"))); }; // Define an options instance to explicitly set the write concern for the transaction operations mongocxx::options::transaction opts; mongocxx::write_concern wc; wc.acknowledge_level(mongocxx::write_concern::level::k_majority); opts.write_concern(wc); // Start a client session auto session = client.start_session(); try { // Start a transaction, execute the operations in the callback function, and commit the results session.with_transaction(callback, opts); } catch (const mongocxx::exception& e) { std::cout << "An exception occurred: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS;
Core API
Use a API principal para gerenciar o ciclo de vida de sua transação. Para implementar essa API, você deve fazer chamadas explícitas para métodos na interface mongocxx::client_session para iniciar uma transação, confirmar uma transação ativa e encerrar uma transação se ocorrer um erro. A API Central não incorpora automaticamente a lógica de tratamento de erros e, em vez disso, permite implementar lógica de tratamento personalizada para erros, incluindo TransientTransactionError e UnknownTransactionCommitResult.
A tabela a seguir descreve os métodos da API principal fornecidos pela interface mongocxx::client_session:
Método | Descrição |
|---|---|
| Inicia uma nova transação na sessão atual do cliente . Aceita uma |
| Confirma a transação ativa na sessão atual do cliente . |
| Termina a transação ativa na sessão atual do cliente . |
Dica
A classe mongocxx::client_session também fornece métodos para recuperar e modificar propriedades da sessão. Para saber mais, consulte mongocxx::client_session na documentação da API.
O código a seguir usa a API Central para executar uma transação que insere documentos nas collections movies e comments no banco de dados sample_mflix. Este código executa as seguintes ações:
Inicia uma sessão a partir do cliente utilizando o método
start_session().Cria um objeto de opção para se preparar para definir a preocupação de gravação para as operações de transação. Para saber mais sobre semântica de leitura e escrita, consulte a seção Read Concern/Write Concern/Read Preference no manual do MongoDB Server .
Chama o método
start_transaction()para iniciar uma transação, passando o objeto de opção como um argumento.Executa operações para inserir documentos em collections no banco de dados
sample_mflix, passando a sessão ativa para cada operação. Se uma operação encontrar um erro, toda a transação será abortada. Se o erro tiver o rótuloTransientTransactionError, a transação será repetida.Confirma a transação ativa usando o método
commit_transaction(). Se a confirmação encontrar um erro com o rótuloUnknownTransactionCommitResult, a confirmação será repetida.
// Establish a connection to the MongoDB deployment mongocxx::instance instance{}; mongocxx::client client(mongocxx::uri{"<connectionString>"}); // Runs the txn_func and retries if TransientTransactionError occurs using transaction_func = std::function<void(mongocxx::client_session& session)>; auto run_with_retry = [](transaction_func txn_func, mongocxx::client_session& session) { while (true) { try { txn_func(session); // performs transaction. break; } catch (const mongocxx::operation_exception& oe) { std::cout << "Transaction aborted. Caught exception during transaction." << std::endl; // If transient error, retry the whole transaction. if (oe.has_error_label("TransientTransactionError")) { std::cout << "TransientTransactionError, retrying transaction..." << std::endl; continue; } else { throw oe; } } } }; // Commits the active transaction and retries commit if UnknownTransactionCommitResult occurs auto commit_with_retry = [](mongocxx::client_session& session) { while (true) { try { session.commit_transaction(); // Uses write concern set at transaction start. std::cout << "Transaction committed." << std::endl; break; } catch (const mongocxx::operation_exception& oe) { // Can retry commit if (oe.has_error_label("UnknownTransactionCommitResult")) { std::cout << "UnknownTransactionCommitResult, retrying commit..." << std::endl; continue; } else { std::cout << "Error during commit..." << std::endl; throw oe; } } } }; auto txn_func = [&](mongocxx::client_session& session) { auto& client = session.client(); // Define database and collection variables auto db = client["sample_mflix"]; auto movies_collection = db["movies"]; auto comments_collection = db["comments"]; // Define an options instance to explicitly set the write concern for the transaction operations mongocxx::options::transaction opts; mongocxx::write_concern wc; wc.acknowledge_level(mongocxx::write_concern::level::k_majority); opts.write_concern(wc); session.start_transaction(opts); // Attempt to insert documents into database collections try { movies_collection.insert_one(session, make_document(kvp("title", "Parasite"))); comments_collection.insert_one(session, make_document(kvp("name", "Anjali Patel"), kvp("text", "This is my new favorite movie!"))); } catch (const mongocxx::operation_exception& oe) { std::cout << "Caught exception during transaction, aborting." << std::endl; session.abort_transaction(); throw oe; } commit_with_retry(session); }; // Start a client session auto session = client.start_session(); try { run_with_retry(txn_func, session); } catch (const mongocxx::operation_exception& oe) { // Do something with error throw oe; }
Informações adicionais
Para saber mais sobre os conceitos discutidos neste guia, consulte as seguintes páginas no manual do MongoDB Server :
Para saber mais sobre a conformidade do ACID , consulte o guia Propriedades do ACID em sistemas de gerenciamento de banco de dados no site do MongoDB .
Para saber mais sobre operações de inserção, consulte o guia Inserir documento .
Documentação da API
Para saber mais sobre qualquer um dos tipos ou métodos discutidos neste guia, consulte a seguinte documentação da API: