sql >> Databáze >  >> RDS >> Mysql

Jak zjistit, že transakce již byla zahájena?

Rámec nemá žádný způsob, jak zjistit, zda jste zahájili transakci. Můžete dokonce použít $db->query('START TRANSACTION') o kterých by framework nevěděl, protože neanalyzuje příkazy SQL, které provádíte.

Jde o to, že je odpovědností aplikace sledovat, zda jste zahájili transakci nebo ne. Není to něco, co framework dokáže.

Vím, že některé frameworky se o to pokoušejí a dělají cockamamie věci, jako je počítání, kolikrát jste zahájili transakci, a vyřeší to pouze tehdy, když jste provedli commit nebo rollback odpovídající počet opakování. Ale to je zcela falešné, protože žádná z vašich funkcí nemůže vědět, zda to commit nebo rollback skutečně provede, nebo jestli jsou v jiné vrstvě vnoření.

(Můžete říct, že jsem tuto diskuzi vedl několikrát? :-)

Aktualizace 1: Propel je knihovna pro přístup k databázi PHP, která podporuje koncept "vnitřní transakce", která se nepotvrdí, když jí to řeknete. Zahájení transakce pouze zvýší počítadlo a potvrzení/vrácení sníží počítadlo. Níže je výňatek z vlákna konference, kde popisuji několik scénářů, kdy selže.

Aktualizace 2: Doktrína DBAL má také tuto vlastnost. Říkají tomu Transaction Nesting.

Ať se vám to líbí nebo ne, transakce jsou „globální“ a nepodléhají objektově orientovanému zapouzdření.

Problémový scénář č. 1

Volám commit() , jsou mé změny potvrzeny? Pokud běžím uvnitř "vnitřní transakce", nejsou. Kód, který spravuje vnější transakci, by se mohl rozhodnout vrátit zpět a moje změny by byly bez mého vědomí nebo kontroly zahozeny.

Například:

  1. Model A:zahájení transakce
  2. Model A:Proveďte některé změny
  3. Model B:zahájení transakce (tiché ne-op)
  4. Model B:proveďte některé změny
  5. Model B:potvrzení (tiché ne-op)
  6. Model A:vrácení zpět (zahodí změny modelu A i změny modelu B)
  7. Model B:WTF!? Co se stalo s mými změnami?

Problémový scénář č. 2

Vnitřní transakce se vrátí zpět, mohla by zrušit legitimní změny provedené vnější transakcí. Když je kontrola vrácena vnějšímu kódu, věří, že jeho transakce je stále aktivní a je k dispozici pro potvrzení. S vaším patchem by mohli zavolat commit() a protože transDepth je nyní 0, nastavilo by tiše $transDepth na -1 a vrátí hodnotu true poté, co nic neprovedete.

Scénář problému č. 3

Pokud zavolám commit() nebo rollback() když není aktivní žádná transakce, nastaví $transDepth na -1. Další beginTransaction() zvýší úroveň na 0, což znamená, že transakci nelze vrátit zpět ani potvrdit. Následná volání funkce commit() pouze sníží transakci na -1 nebo více a nikdy nebudete moci provést potvrzení, dokud neprovedete další zbytečnou beginTransaction() pro opětovné zvýšení úrovně.

V zásadě je pokus o správu transakcí v aplikační logice bez toho, aby databáze vedla účetnictví, nápadem odsouzeným k zániku. Pokud požadujete, aby dva modely používaly explicitní řízení transakcí v jedné žádosti aplikace, musíte otevřít dvě DB připojení, jedno pro každý model. Každý model pak může mít svou vlastní aktivní transakci, kterou lze potvrdit nebo vrátit zpět nezávisle na sobě.



  1. Úvod do nasazení MySQL pomocí Ansible role

  2. SQL EXISTS Operátor pro začátečníky

  3. Jak mohu získat přístup k příkazovému řádku MySQL pomocí XAMPP pro Windows?

  4. Nejlepší typ pole databáze pro adresu URL