Transações
Nesta página
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 mongoxcc::client
instância 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 forquilhas.
APIs de transações
O driver C++ do MongoDB fornece uma API de chamada de resposta de chamada e uma API principal 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 chamada de resposta de resposta 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 de chamada 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 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 de resposta para executar uma transação que insere documentos nas coleção movies
e comments
no banco de 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 de chamada 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 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 principal não incorpora automaticamente a lógica de tratamento de erros e, em vez disso, permite que você implemente a lógica de tratamento personalizada para erros, incluindo TransientTransactionError
e UnknownTransactionCommitResult
.
A tabela a seguir descreve os principais métodos de API fornecidos pela interface mongocxx::client_session
:
Método | Descrição |
---|---|
| Starts a new transaction on the current client session. Accepts an optional mongocxx::options::transaction
instance as an argument to set options. For a full list of options, see mongocxx::options::transaction
in the API documentation.Raises an exception if the options are misconfigured, if there are network or other transient failures, or if there
are other errors such as a session with a transaction already in progress. If an error is returned with the TransientTransactionError label,
you can end the transaction and then retry it with the expectation that it will succeed.To learn more about this method, see the startTransaction() guide in the MongoDB Server manual. |
| Commits the active transaction on the current client session. Raises an exception if options are misconfigured, if there are network or other transient failures,
or if there are other errors such as a session with no transaction in progress. If an error is returned with the UnknownTransactionCommitResult label,
you can end the transaction and then retry it with the expectation that it will succeed when the committed transaction satisfies the set write concern.To learn more about this method, see the commitTransaction() guide in the MongoDB Server manual. |
| Ends the active transaction on the current client session. Raises an exception if the options are misconfigured or if there are other errors such as
a session with no transaction in progress. To learn more about this method, see the abortTransaction() guide in the MongoDB Server manual. |
Dica
A mongocxx::client_session
classe 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 principal para executar uma transação que insere documentos nas coleções movies
e comments
no banco de 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 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á tentada novamente.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: