Kom ihåg mig?
Home Menu

Menu


MySQL transaktion

 
Ämnesverktyg Visningsalternativ
Oläst 2010-11-11, 21:26 #1
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
Standard MySQL transaktion

Hej,
Jag ska hämta några rader från en tabell, och sedan utföra en del tidskrävande beräkningar på datan, och sedan stoppa tillbaks/uppdatera samma data till tabellen. Jag vill inte låsa tabellen under hela tiden som jag utför beräkningarna, och jag vill inte heller riskera att olika sessioner utför beräkningar på samma data. Mitt förslag på lösning är att använda en busy-flagga, på så sätt behöver jag endast låsa tabellen en kort tid...

Pseudokod:
1. Lås tabellen
2. Hämta rader som har busyflagga = 0
3. Uppdatera hämtade raders busyflagga till 1
4. Öppna tabellen
5. Utför de tidskrävande beräkningarna
6. Uppdatera raderna med ny data, samt sätt busyflaggan till 0

Mina frågor är
- Är detta "rätt" sätt att lösa problemet?
- Hur gör jag för att låsa en MySQL tabell med php?
hoover är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-11, 21:52 #2
studiox studiox är inte uppkopplad
Har WN som tidsfördriv
 
Reg.datum: Aug 2004
Inlägg: 1 356
studiox studiox är inte uppkopplad
Har WN som tidsfördriv
 
Reg.datum: Aug 2004
Inlägg: 1 356
Du kan köra transactions på "riktigt" om du kör InnoDB. Då släpps inte tabellen förrän du kör en "execute done".

Kan du inte läsa in allt data i minnet istället och sen uppdatera? På vilket sätt skulle andra "sessions" förstöra för dig? Du kontrollerar väl dom med?
studiox är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-11, 22:16 #3
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
Citat:
Ursprungligen postat av studiox Visa inlägg
Kan du inte läsa in allt data i minnet istället och sen uppdatera?
Jo, det är planen. Men jag vill inte låsa tabellen under alla de sekunder som jag arbetar med datan.
Citat:
Ursprungligen postat av studiox Visa inlägg
På vilket sätt skulle andra "sessions" förstöra för dig? Du kontrollerar väl dom med?
När olika användare efterfrågar en php-sida så kommer SQL-frågan att exekveras och samma data riskeras att hämtas av olika användare om jag inte låser, eller använder flagga under arbetet med datan.
hoover är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-11, 22:18 #4
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Tidskrävande kanske tyder på att frågan kan optimeras.

Annars är det bästa normalt att använda de inbyggda transaktionsmöjligheter som databasen erbjuder och INTE hitta på egna busyflaggor för databasen kan oftast hantera detta bättre.

Nu vet jag inte hur din fråga är uppbyggd men ett sätt kan vara att uppdatera en post i ttaget i databasen med en updatesats och sedan flagga den med att den är "beräknad".

Kod:
-- Har inte kollat syntaxen .... 
-- tanken är att denna fråga körs många gånger tills alla 
-- poster blivit uppdaterade med det nya beräknade värdet
-- Begin Transaction
UPDATE myTable
SET oldValue=(Select ... AS NewValue FROM ... WHERE ...)
SET UpdatedValueFlagga=Now()
WHERE AND ID=
(
    SELECT TOP 1 ID
    FROM MyTable
    WHERE UpdatedValueFlagga IS NULL
)
-- End transaction
Svårt att avgöra vilka alternativ som finns när man inte vet hur viktigt att uppdatering körs samtidigt som databasen är uppe. Men om du kan beräkna värdet för sig och när värdet väl är beräknat så kan du uppdatera databasen med värdet, då går det snabbare med en updatefråga och du kanske kan låsa tabellen under de sekunder som krävs.

Senast redigerad av Conny Westh den 2010-11-11 klockan 22:35
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-12, 09:50 #5
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
Citat:
Ursprungligen postat av ConnyWesth Visa inlägg
Tidskrävande kanske tyder på att frågan kan optimeras.
Det är inte frågan som är tidskrävande, det är det arbete jag utför på hämtad data. Tror inte jag kan utföra det utan busyflagga eftersom det är uteslutet att låsa tabellen under den långa tid som arbetet med datan tar.
1. Jag hämtar datan
2. Jag arbetar med datan (involverar externa API etc som är tidskrävande)
3. jag uppdaterar datan i min databas med modifierade värden.

Har googlat lite mer, vad tror ni om nedanstående approach?

BEGIN
SELECT * FROM table WHERE x=y AND busy = 0
UPDATE table SET busy = 1 WHERE x=y
COMMIT

zzzzz beräkning av nya värden zzzzzz

UPDATE table SET oldvalue = newvalue, busy = 0 WHERE x=y


Då låser jag tabellen endast en kort tid, men säkerställer ändå att inte olika skript arbetar parallellt med samma data. Eller?
hoover är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-12, 12:04 #6
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Conny Westh Conny Westh är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Aug 2005
Inlägg: 5 166
Vad jag menar är att du kanske kan uppdatera en post i taget och därmed korta ner tiden som hela din transaktion tar.

Försök att bygga din rutin så att du bara behöver låsa den enskilda posten när du kör din fråga mot det externa APIet, så du kan använda BEGIN ... COMMIT och sen vara klar med den enskilda posten. Då ska du inte behöva låsa med busy-flagga för det är knepigt och introducerar andra problem, som kraschproblematik och du har inte transaktionsskyddet som databasen (MySQL med Inno-DB) kan erbjuda.

Kan du hämta det externa datat till en temptabell och bearbeta det där för att sedan uppdatera orginaltabellen när din beräkning är klar?

Senast redigerad av Conny Westh den 2010-11-12 klockan 13:04
Conny Westh är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-12, 12:51 #7
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
hoover hoover är inte uppkopplad
Nykomling
 
Reg.datum: Jan 2004
Inlägg: 48
Citat:
Ursprungligen postat av ConnyWesth Visa inlägg
Vad jag menar är att du kanske kan uppdatera en post i taget och därmed korta ner tiden som hela din transaktion tar.

Försök att bygga din rutin så att du bara behöver låsa den enskilda posten när du kör din fråga mot det externa APIet, så du kan använda BEGIN ... COMMIT och sen vara klar med den enskilda posten. Då ska du inte behöva låsa med busy-flagga för det är knepigt och introducerar andra problem, som kraschproblematik och du har inte transaktionsskyddet som dataasden kan erbjuda.

Kan du hämta det externa datat till en temptabell och bearbeta det där för att sedan uppdatera orginaltabellen när din beräkning är klar?
Tack för hjälpen, det enda som är kritiskt i mitt fall är att inte samma rader bearbetas parallellt, kraschproblematiken kan jag leva med. Eftersom jag redan har implementerat flaggan, så jag kör på den lösningen ett tag. Om det blir för mycket strul ska jag prova ditt förslag.
hoover är inte uppkopplad   Svara med citatSvara med citat
Oläst 2010-11-12, 12:39 #8
Clarence Clarence är inte uppkopplad
Administratör
 
Reg.datum: Jan 2003
Inlägg: 1 974
Clarence Clarence är inte uppkopplad
Administratör
 
Reg.datum: Jan 2003
Inlägg: 1 974
Ett enkelt alternativ som jag ibland väljer är att lägga till (de relevanta delarna av) raderna i en kö, eventuellt med unikt index över aktuella fält, för kommande jobb att utföra. Sen har du ett script som med jämna mellanrum kollar av om det finns nya jobb att utföra. Det scriptet kan sedan fördela arbetet till fler processer om du vill kunna utföra det parallellt (beroende på de externa APIerna kanske det inte ens är önskvärt?).

Skulle det sedan vid någon punkt bli väldigt mycket jobb att utföra är det enkelt att utöka och effektivisera ett sådant system genom t ex gearman.

Använder du transaktioner så se till att, som studiox sa, använda innodb-tabeller då de är den enda (default-shippade) tabelltypen med transaktionsstöd för mysql.
Clarence är inte uppkopplad   Svara med citatSvara med citat
Svara


Aktiva användare som för närvarande tittar på det här ämnet: 1 (0 medlemmar och 1 gäster)
 

Regler för att posta
Du får inte posta nya ämnen
Du får inte posta svar
Du får inte posta bifogade filer
Du får inte redigera dina inlägg

BB-kod är
Smilies är
[IMG]-kod är
HTML-kod är av

Forumhopp


Alla tider är GMT +2. Klockan är nu 01:20.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson
 
Copyright © 2017