Avatar billede razmuzdk Nybegynder
20. november 2006 - 22:24 Der er 6 kommentarer og
2 løsninger

Transactions - men uden at låse tabeller!

Jeg har lavet et website hvor brugere kan købe fiktive ting af hinanden.

Der er nu opstået det problem, at nogle kreative brugere har fundet ud af, at hvis du trykker på "Køb" lynhurtigt efter hinanden - så kan de snyde sig til mange fiktive penge.

Mit "køb-script" ser sådan ud i pseudokode:
// tjek om tilbudet findes
// hvis tilbud findes {
// slet tilbud (så man ikke kan foretage samme køb igen)
// træk penge fra sælger
// tilføj penge til køber
// afslut handel }

PRoblemet er, at hvis dette script eksekveres MEGET MEGET tæt på samme tidspunkt, så vil tilbudet ikke blive slettet før "tjek om tilbudet findes" køres 2. gang (af en sideløbende proces fordi brugeren klikker hurtigt på samme link mange gange).

Jeg ville jo klart kunne løse problemet med transactions - men jeg er ikke interesseret i at låse mine tabeller. Det vil få mit site til at gå alt for langsomt.

Hvordan kan man ellers gøre?

Mit løsningsforslag ville være, at i stedet for foretage "købsprocessen" når brugeren klikker på et tilbud (med tjek om tilbud findes, træk penge, tilføj penge, afslut handel osv.) - så vil der blive oprette en record om, at brugeren gerne vil benytte sig af det købstilbud. Den record vil blive læst af et cronjobs som kører ofte. På den måde vil der aldrig blive oprettet to simultane kørsler af et "køb-script".

Kan du se en bedre løsning end den jeg forslår ovenfor?

På forhånd tak.

- Rasmus
Avatar billede AnyFellow Mester
20. november 2006 - 22:29 #1
Jeg går ud fra du mener at brugerne kan snyde sig til mange fiktive penge ved "sælg"?

Du kan sætte et timestamp på hver handel og så lave således det ikke er muligt for samme bruger at købe/sælge samme vare til/af samme person i et bestemt tidsrum, f.eks. 1 minut.

Du kan deaktivere knappen de trykker på med noget java-halløj (ikke speciel sikker, men som en "ekstra-ting" kunne den være okay.

Hvis du bruger sessions, kan du sikkert lave en kontrol af om de har lavet mere end én handel inden for få sekunder.
Avatar billede razmuzdk Nybegynder
20. november 2006 - 22:36 #2
Hej kfisker,

TAk for dit hurtige svar.

Ja jeg mente salg :-)

Det med timestamp går ikke - forestil dig hvis købs-/salgsprocessen bliver aktiveret 2 gange på NÆSTEN samme tid. Så vil det tjek, der ser om brugeren har handlet inden for det sidste minut ske FØR brugertabellen bliver opdateret med "sidste_handel = NOW()". Derfor nytter det ikke noget.

Ja, jeg kunne deaktivere knappen med JS- men så er det et spørgsmål om tid inden nogen finder ud af kalde url'en direkte via browseren adresse-linje.

Det med sessions - det tror jeg muligvis vil virke :P Jeg tester det lige og vender tilbage... :)
Avatar billede arne_v Ekspert
21. november 2006 - 01:49 #3
jeg mener at du bør bruge transactions - de er beregnet til det og performance bør
ikke forringes så meget (ihvertfald ikke hvis du allerede bruger InnoDB tabeller)
Avatar billede arne_v Ekspert
21. november 2006 - 01:50 #4
et alternativ hvis dit database API returnerer antal rækker for execute er

hvis slet tilbud returnerer antal rækker > 0 {
  træk penge fra sælger
  tilføj penge til køber
  afslut handel
}
Avatar billede razmuz_dk Nybegynder
21. november 2006 - 15:45 #5
Hej kfisker og arne,

Jeg forsøgte mig via php at kontrollere det med sessions - det viste sig til min overraskelse ikke at være sikkert nok. Der var simpelthen en eller anden form for "forsinkelse" på hvornår session'en blev "synlig" for de andre simultane processor.

Men arnes måde at gøre tingene på (det sidst-nævnte) er da idiotsikker vil jeg umiddelbart sige. I uhyre sjældne tilfælde kan processen stoppes efter pengene er trukket fra sælger og efter pengene er tilføjet til køber, hvilket jo kunne fixes ved at bruge transactions. Men det er for voldsomt i "første omgang".

Jeg har nu sat en if(mysql_affected_rows() == 0) ind for at teste hvorvidt tilbudet findes... det er jeg ret overbevist om i det mindste forhindrer snyd.

Tak for begge jeres svar. I fortjener vidst begge point - så smid et svar :o)
Avatar billede razmuz_dk Nybegynder
21. november 2006 - 15:50 #6
Ups, ovenstående fik jeg vidst skrevet for hurtigt. Der skulle naturligvis stå "EFTER pengene er trukket fra køber og FØR pengene er tilføjet til sælger" :-)

Og skal jeg vidst snart lære at stave til processor! :)
Avatar billede arne_v Ekspert
22. november 2006 - 01:07 #7
svar
Avatar billede AnyFellow Mester
23. november 2006 - 10:39 #8
Svar :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester