Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Por que o Rails ignora um Rollback em uma transação (pseudo)aninhada?


Na verdade, é exatamente assim que as transações aninhadas foi projetado para. Eu cito de documentos oracle:

Portanto, uma transação filha em uma transação aninhada regular não tem nada a dizer sobre como ele ou os outros filhos ou pais (transação maior ) poderia se comportar, além de alterar dados mútuos ou falhar por uma exceção.

Mas você pode conceder a ele (transação filha ) uma chance de voto muito limitada em seu destino, utilizando a sub-transaction recurso conforme declarado em rails docs passando requires_new: true
User.transaction do
  User.create(username: 'Kotori')
  User.transaction(requires_new: true) do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end

Que como dizem os documentos:apenas cria 'Kotori'. desde que a poderosa criança 'Nemu' escolheu morrer silenciosamente.

Mais detalhes sobre Regras de transações aninhadas (documentos oracle )

Atualização:

Para entender melhor por que Rails nested transactions funciona dessa maneira, você precisa saber um pouco mais sobre como as transações aninhadas funcionam no nível do banco de dados, cito documentos da API Rails :

Ok, então a documentação descreve o comportamento de uma nested transaction nos dois casos mencionados da seguinte forma:

No caso de uma chamada aninhada, #transaction vai se comportar da seguinte forma:

  • O bloco será executado sem fazer nada. Todas as instruções de banco de dados que ocorrem dentro do bloco são efetivamente anexadas à transação de banco de dados já aberta.

  • No entanto, se :requires_new estiver definido, o bloco será encapsulado em um ponto de salvamento do banco de dados atuando como uma subtransação.

Imagino cuidado, apenas imagine que:

opção(1) (sem require_new) existe caso você tenha usado um DBMS que suporte totalmente nested transactions ou você está satisfeito com o comportamento "falso" de nested_attributes

enquanto opção(2) é suportar o savepoint solução alternativa se você não fizer isso.