[PHP/Mysql5] (Virtuele) multi-request transacties?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12
Ik ben vandaag samen met m'n collega even aan't stoeien geweest om bepaalde acties die op een database (mysql 5.0/innodb) uitgevoerd worden in een transactie te wrappen om deze zo ook weer ongedaan te kunnen maken.

Op zich helemaal geen probleem, maar het probleem is dat deze transactie over meerdere requests uitgespreid moet kunnen worden.

Een simpel idee leek me om dan mysql_pconnect te gebuiken zodat je db connectie opengehouden wordt tussen requests en je weer lekker verder kan met je transactie. Helaas, er blijkt een connection pool opgezet te worden en het blijkt te kunnen zijn dat je een connectie toegespeeld krijgt waar heel jouw transactie niet geldig is (of nog erger, de transactie van een andere user)


Op PHP.net en andere sites zeggen eigenlijk hetzelfde: een transactie kan niet over meerdere requests uitgespreid worden.

Zijn er mensen die andere oplossingen uitgevonden hebben, of geniale ideeën over een mogelijke oplossing?

Een van de ideeën waar ik zelf momenteel mee in m'n hoofd zit is het volgende:

• een transactie class die rechtstreeks in m'n dbConnection object vastgeknoopt zit
• zodra je dbConnection->startTransaction() aanroept worden alle komende (insert/update/delete) queries gelogged naar de sessie
• aan het eind van de sessie worden alle transacties automagisch ge-RollBack't.
• elke volgende request wordt automagisch gekeken of de sessie weer opnieuw ge-init moet worden en worden alle insert/update/delete queries weer uitgevoerd, zodat de transactie weer 'overnieuw afgespeeld' is.
• pas op het moment dat je expliciet commit wordt je transactie afgesloten en de queries uit de sessie weer leeggemaakt.

Iemand nog andere tips/tricks?

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • djiwie
  • Registratie: Februari 2002
  • Laatst online: 17-09 16:35

djiwie

Wie?

Het idee om je queries in een sessie te zetten en aan het einde expliciet uit te voeren lijkt me nog niet eens zo gek. Je kunt bijvoorbeeld een array maken (in een sessie-variabele), en die op het moment dat je wilt committen uitlezen en uitvoeren. Wil je tussentijds al rollbacken, dan maak je gewoon de array leeg (je queries zijn immers nog niet uitgevoerd in het RDBMS).

Maar iets anders kan ik niet zo snel verzinnen, en volgens mij bestaat er ook niet echt een standaardoplossing voor.

Acties:
  • 0 Henk 'm!

  • eamelink
  • Registratie: Juni 2001
  • Niet online

eamelink

Droptikkels

Een transactie over meerdere requests lijkt mij ook niet zo'n goed idee. De gedachte dat er allemaal locks liggen op rows in je database, terwijl je user koffie aan het halen is maakt mij niet echt blij :P

Je oplossing lijkt me wel aardig al vraag ik me af wat de noodzaak is om bij elke request opnieuw alles te laten executen en mogelijk weer rollbacken? Kan je dan niet beter meteen alles in een sessievariabele stoppen en pas bij de eindpagina committen? Of ben je afhankelijk van mogelijke foutmeldingen bij een query halverwege?

Ik ben ook wel benieuwd naar het scenario waarin zich dit afspeelt :P

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik zou eens kijken naar een UnitOfWork-achtig iets; dan kun je een aantal 'opdrachten' verzamelen en die in 1 transactie verwerken. Dus een soort queue waarin je alle opdrachten bij elkaar 'verzamelt' om daarna in 1 transactie (zonder tussenliggende requests dus) uit te voeren. Maar dat lijkt dus verdacht veel op wat je van plan bent. Of een sessie zo'n goed idee is weet ik niet (want die verlopen soms nog wel eens :P ), maar "ergens" je UoW opslaan en dan verwerken is dus wel de strekking ja ;)

[ Voor 24% gewijzigd door RobIII op 09-11-2007 01:27 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12
Oke op verzoek even het idee wat hier achter ligt in vogelvlucht.

Ik ben inmiddels zo ver met alle classes om m'n o/r mapper heen dat ik bijna automagisch een complete backend kan genereren voor bijna elke willekeurige database. CRUD van records, maar vooral ook het hangen van relaties naar de verschillende gekoppelde tabellen (die je toch al weet door de O/R mapping)

De process flow van de applicatie is ongeveer als volgt: (ik heb wat images toegevoegd voor de duidelijkheid)
• Gebruiker kiest bijv. nieuws item -> toevoegen
[ 1 ] Gebruiker krijgt een form voor z'n neus waar hij z'n nieuws item toevoegt, slaat op, en komt dan in hetzelfde scherm weer terug (nu heeft hij een ID gegeven aan het record wat hij ging toevoegen)
[ 2 ] Nu komt (omdat er al een ID is voor dit record) de gestandaardiseerde relatie editor in beeld:
[ 3 ] Gebruiker wil bijv. aan dit nieuwsitem een sector koppelen, klikt op koppelen. Er wordt nu een ajax request afgevuurd welke in de db kijkt naar welke records er al gekoppeld zijn aan dit ID en alle records behalve de gekoppelde worden in een lijst terugegeven
[ 4 ] Gebruiker koppelt bijv. de sector bloemisterij, er wordt weer een ajax request afgevuurd die zegt -> leg de relatie tussen dit object, en het sector object bloemisterij
[ 5 ] Lijstje wordt getoond van welke sectoren er nu aan het nieuws object getoond zitten

Dit werkt momenteel allemaal prachtig, in theorie én in de praktijk, alleen nu krijg je dus de wens van de gebruiker die niet éérst wil saven maar ook gelijk relaties kunnen koppelen :+ Ergo, als ik niet m'n hele zooi wil hoeven ombouwen heb ik een soort van 'virtual' insert ID nodig, of een transactie over meerdere requests die ik later weer ongedaan kan maken als de gebruiker besluit niet aan alle validaties te voldoen of hij het scherm verlaat zonder op te slaan.

Daardoor was dus de oplossing in m'n hoofd gekomen: een soort virtuele transactie die elk requestje (wat toch maar heel kort duurt omdat het ajax calls zijn) de database transactie weer in dezelfde state brengt als daarvoor, zijn ding doet, en automagisch weer rollbackt :)

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • djiwie
  • Registratie: Februari 2002
  • Laatst online: 17-09 16:35

djiwie

Wie?

Maar waarom zou je een query uitvoeren en meteen weer rollbacken? Volgens mij kun je beter in een sessie o.i.d. opslaan welke relaties er gelegd moeten worden, en bij het opslaan van de pagina alle queries daarvoor uitvoeren (als de id eenmaal bekend is).
Met tussentijds queries uitvoeren en weer rollbacken belast je alleen maar de database server terwijl dat niet nodig is imho.

Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12
djiwie schreef op vrijdag 09 november 2007 @ 08:27:
Maar waarom zou je een query uitvoeren en meteen weer rollbacken? Volgens mij kun je beter in een sessie o.i.d. opslaan welke relaties er gelegd moeten worden, en bij het opslaan van de pagina alle queries daarvoor uitvoeren (als de id eenmaal bekend is).
Met tussentijds queries uitvoeren en weer rollbacken belast je alleen maar de database server terwijl dat niet nodig is imho.
Ik wil hem eigenlijk pas weer rollback'en aan het einde van de request. Mijn idee is dus dat je een 'virtueel' nieuw record id insert (welke ID hij krijgt vanuit binnen de transactie) en dan dat elke keer naspeelt zodat de transactie weer 'in sync' is met wat er de vorige requests gebeurde.

Ik heb inderdaad ook nagedacht over de relaties voor een nieuw object nabootsen via een sessie ofzo maar dan moet ik echt rigoreus alles wat ik nu gebouwd heb (en wat nou juist zo mooi werkt 'live' via ajax request weer gaan ombouwen zodat het alleen in het geval van een nieuw record de sessie gaat gebruiken en dat klinkt ook een beetje ranzig als je het mij vraagt (want dat moet dan op een zodanig diep niveau ge-emuleerd worden dat je relaties kan vinden van een object wat nog niet bestaat)

Door de insert/edit/delete queries in de sessie te gooien en uit te voeren binnen de transactie kan je dus wél de ID's verkrijgen die ik nodig heb en door de transactie te rollback'en is het daarna weer of er niets gebeurd is en krijg je dus geen vervuiling in je DB.
Qua overhead zal het volgens mij best meevallen trouwens, er gebeuren volgens mij uiteindelijk max 10 insert queries als je eens zo'n heel proces doorgelopen bent.

[ Voor 14% gewijzigd door SchizoDuckie op 09-11-2007 09:33 ]

Stop uploading passwords to Github!


Acties:
  • 0 Henk 'm!

  • twiekert
  • Registratie: Februari 2001
  • Nu online
Een rollback reset geen auto increment columns naar de vorige waarde voor de INSERT, wel iets om rekening mee te houden, daarnaast is het niet multi-user compatible.

Volgens mij gaat de manier waarop je het nu bedenkt niet echt geweldig werken. Feit is dat de procedure voor het updaten van een bestaand record nu anders is dan het toevoegen van een nieuw record.

Je ontkomt er niet aan om de opdrachten die je wilt uitvoeren eerst van te voren moet gaan verzamelen om ze vervolgens als één transactie uit te voeren. :)
Deze opdrachten moeten ergens vast gelegd worden (session, cookie, post/get var).

[ Voor 3% gewijzigd door twiekert op 09-11-2007 11:36 ]


Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50

BikkelZ

CMD+Z

Met vaste temporary, eventueel memory tables werken waarin de voorlopige op te slaan resultaten in worden gebufferd waarop de volgende query weer op los gelaten wordt. Maar dit wil je echt niet denk ik.

iOS developer


Acties:
  • 0 Henk 'm!

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12
Hmm nee. het is inderdaad allemaal niet echt practisch dan hoe het zo inelkaaar (gaat) steken. ik ga er nog even over brainstormen met mezelf :) thanks voor de responses :)

Stop uploading passwords to Github!

Pagina: 1