Mysql
 sql >> Database >  >> RDS >> Mysql

Perché Rails ignora un rollback in una transazione (pseudo) annidata?

In realtà questo è esattamente come Transazioni nidificate è stato progettato per. Cito da Oracle Docs:

Quindi, una transazione secondaria in una normale transazione nidificata non ha voce in capitolo su come lui o gli altri figli o genitori (transazione più ampia ) potrebbe comportarsi diversamente dalla modifica dei dati reciproci o dal fallimento per un'eccezione.

Ma puoi concedergli (transazione figlio ) una possibilità di voto molto limitata sul suo destino utilizzando la sub-transaction funzione come indicato in 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

Che come dicono i documenti:crea solo 'Kotori'. dal momento che il potente bambino 'Nemu' ha scelto di morire in silenzio.

Maggiori dettagli sulle Regole delle transazioni nidificate (documenti Oracle )

Aggiornamento:

Per capire meglio perché blocca nested transactions funziona in questo modo, devi sapere un po' di più su come funzionano le transazioni nidificate a livello di database, cito da documenti API Rails :

Ok, allora i documenti descrivono il comportamento di una nested transaction nei due casi citati come segue:

In caso di chiamata annidata, #transaction si comporterà come segue:

  • Il blocco verrà eseguito senza fare nulla. Tutte le istruzioni del database che si verificano all'interno del blocco vengono effettivamente aggiunte alla transazione del database già aperta.

  • Tuttavia, se :requires_new è impostato, il blocco verrà racchiuso in un punto di salvataggio del database che funge da sottotransazione.

Immagino attento, immagino solo che:

opzione(1) (senza require_new) è presente nel caso in cui tu abbia utilizzato un DBMS che supporta pienamente le nested transactions oppure sei soddisfatto del comportamento "falso" di nested_attributes

mentre opzione(2) è supportare il savepoint soluzione alternativa in caso contrario.