Visão geral
Neste guia, você pode aprender a usar o driver Scala para executar transações. As transações permitem que você execute uma série de operações que alteram os dados somente se toda a transação estiver confirmada. Se qualquer operação na transação não for bem-sucedida, o driver interromperá a transação e descartará todas as alterações de dados antes que elas se tornem visíveis. Esse recurso é chamado de atomicidade.
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ê deseja executar sequencialmente. As sessões permitem consistência causal para um grupo de operações e permitem executar 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 usar o driver Scala, você pode iniciar um ClientSession
chamando o método startSession()
em seu cliente. Em seguida, você pode realizar transações dentro da sessão.
Aviso
Use um ClientSession
somente em operações executadas no MongoClient
que o criou. Utilizar uma ClientSession
com um MongoClient
diferente resulta em erros de operação.
Métodos
Após chamar o método startSession()
para iniciar uma sessão, você pode utilizar métodos da classe ClientSession
para modificar o estado da sessão. A tabela a seguir descreve os métodos que você pode usar para gerenciar uma transação:
Método | Descrição |
---|---|
| Starts a new transaction on this session. You cannot start a
transaction if there's already an active transaction running in
the session. You can set transaction options by passing a TransactionOptions
instance as a parameter. |
| Commits the active transaction for this session. This method returns an
error if there is no active transaction for the session, the
transaction was previously ended, or if there is a write conflict. |
| Ends the active transaction for this session. This method returns an
error if there is no active transaction for the session or if the
transaction was committed or ended. |
Dica
Tempo limite da transação
Você pode definir um limite de tempo para que as operações sejam concluídas em suas transações. Para saber mais, consulte a seção Transações do guia Limitar o tempo de execução do servidor.
Exemplo de transação
Este exemplo define um método runTransaction()
que modifica dados nas collections do banco de dados sample_mflix
. O código executa as seguintes ações:
Cria
MongoCollection
instâncias para acessar as coleçõesmovies
eusers
Especifica a preocupação de gravação da transação
Inicia a transação
Insere um documento na coleção
movies
e imprime os resultadosAtualiza um documento na collection
users
e imprime os resultados
def runTransaction( database: MongoDatabase, observable: SingleObservable[ClientSession] ): SingleObservable[ClientSession] = { observable.map(clientSession => { val moviesCollection = database.getCollection("movies") val usersCollection = database.getCollection("users") val transactionOptions = TransactionOptions .builder() .readConcern(ReadConcern.SNAPSHOT) .writeConcern(WriteConcern.MAJORITY) .build() // Starts the transaction with specified options clientSession.startTransaction(transactionOptions) // Inserts a document into the "movies" collection val insertObservable = moviesCollection.insertOne( clientSession, Document("name" -> "The Menu", "runtime" -> 107) ) val insertResult = Await.result(insertObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) println(s"Insert completed: $insertResult") // Updates a document in the "users" collection val updateObservable = usersCollection.updateOne( clientSession, equal("name", "Amy Phillips"), set("name", "Amy Ryan") ) val updateResult = Await.result(updateObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) println(s"Update completed: $updateResult") clientSession }) }
Observação
Dentro de uma transação, as operações devem ser executadas em sequência. O código anterior aguarda o resultado de cada operação de gravação para garantir que as operações não sejam executadas simultaneamente.
Em seguida, execute o seguinte código para executar a transação. Este código conclui as seguintes ações:
Cria uma sessão a partir do cliente utilizando o método
startSession()
Chama o método
runTransaction()
definido no exemplo anterior, passando o banco de dados e a sessão como parâmetrosCompromete a transação chamando o método
commitTransaction()
e aguarda a conclusão das operações
val client = MongoClient("<connection string>") val database = client.getDatabase("sample_mflix") val session = client.startSession(); val transactionObservable: SingleObservable[ClientSession] = runTransaction(database, session) val commitTransactionObservable: SingleObservable[Unit] = transactionObservable.flatMap(clientSession => clientSession.commitTransaction()) Await.result(commitTransactionObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
Insert completed: AcknowledgedInsertOneResult{insertedId=BsonObjectId{value=...}} Update completed: AcknowledgedUpdateResult{matchedCount=1, modifiedCount=1, upsertedId=null}
Observação
Operações paralelas não suportadas
O driver Scala não suporta a execução de operações paralelas dentro de uma única transação.
Se você estiver usando o MongoDB Server v8.0 ou posterior, poderá executar operações de gravação em vários namespaces em uma única transação usando o recurso de gravação em massa do cliente . Para saber mais sobre esse recurso, consulte o guia de Operações de Gravação em Massa.
Informações adicionais
Para saber mais sobre os conceitos mencionados neste guia, consulte as seguintes páginas no manual do MongoDB Server :
Para saber mais sobre a conformidade com ACID , consulte o artigo Um guia para propriedades 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 os métodos e tipos mencionados neste guia, consulte a documentação da API abaixo: