sql >> Database >  >> RDS >> Mysql

Waarom negeert Rails een Rollback in een (pseudo)geneste transactie?

Dit is eigenlijk precies hoe geneste transacties voor is ontworpen. Ik citeer uit orakeldocumenten:

Dus een onderliggende transactie in een gewone geneste transactie heeft geen zeggenschap over hoe hij of de andere kinderen of ouder (grotere transactie ) zich zou kunnen gedragen, behalve het wijzigen van wederzijdse gegevens of het niet slagen voor een uitzondering.

Maar je kunt hem (onderliggende transactie ) een zeer beperkte stemkans op zijn lot door gebruik te maken van de sub-transaction functie zoals vermeld op rails docs door requires_new: true . door te geven

User.transaction do
  User.create(username: 'Kotori')
  User.transaction(requires_new: true) do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end

Wat, zoals de documenten zeggen:alleen 'Kotori' creëert. sinds het machtige 'Nemu'-kind ervoor koos om in stilte te sterven.

Meer details over Geneste transactieregels (oracle docs )

Bijwerken:

Om beter te begrijpen waarom rails nested transactions op deze manier werkt, moet je wat meer weten over hoe geneste transacties werken op DB-niveau, ik citeer uit rails api-documenten :

Ok, dan beschrijven de documenten het gedrag van een nested transaction in de twee genoemde gevallen als volgt:

In het geval van een geneste oproep, #transaction zal zich als volgt gedragen:

  • Het blok wordt uitgevoerd zonder iets te doen. Alle database-instructies die binnen het blok plaatsvinden, worden effectief toegevoegd aan de reeds geopende databasetransactie.

  • Als :requires_new echter is ingesteld, wordt het blok verpakt in een databaseopslagpunt dat als een subtransactie fungeert.

Ik stel me voorzichtig voor, stel je maar voor dat:

optie(1) (zonder vereist_new) is er voor het geval je een DBMS hebt gebruikt dat nested transactions volledig ondersteunt of je bent tevreden met het "nep"-gedrag van nested_attributes

while optie(2) is om het savepoint . te ondersteunen tijdelijke oplossing als u dat niet doet.



  1. MariaDB Cluster offline installatie voor CentOS

  2. Docker (Apple Silicon/M1 Preview) MySQL geen overeenkomend manifest voor linux/arm64/v8 in de manifestlijstvermeldingen

  3. MySQL, meerdere rijen om velden te scheiden

  4. Tijdstempelvelden in django