WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Låsa upp en tabell i mysql så länge jag håller på att putta in data. (https://www.wn.se/forum/showthread.php?t=1065451)

spyvingen 2015-09-02 08:05

Låsa upp en tabell i mysql så länge jag håller på att putta in data.
 
Har nu en sida som ligger och uppdaterar en tabell i mysql var 15:e sekund.

Har sedan en sida där jag presenterar data som uppdateras var 15:e sekund.

Sidan som hämtar har en databas öppning och den gör två sidhämtningar först hämtar den från en sida tar bort alla spår från denna sidan i data basen och sedan puttar in det nya i databasen och sedan samma sak med andra sidan.

När jag nu uppdaterar presentationssidan var 15:E sekund verkar den hämta i något mellan läge så det finns bara data från ena sidan.

Jag har alltid trott att tabellen är låst när man puttar in data men det verkar ju vara fel :)

Så frågan är kan jag tvinga den att vara låst medans jag hämtar data så att min presentationssida får stå i kö tills all data är uppdaterad?

Eller kan jag slå ihop allt till en enda insert på nått sätt så jag bara gör en batch med inserts istället för flera olika så att databasen skriver allt med en förfrågan eller liknande?

Kanske finns bättre sätt än de jag kommit på är inte alls så van vid mysql.

coredev 2015-09-02 08:45

Jag är inte säker på att jag förstår hur din applikation fungerar gällande skriv och läsning. Men låt oss säga att funktionen som bygger upp datat består av en DELETE och en eller flera INSERT, då bör du wrappa dessa i en transaktion. Sedan kan du välja i funktionen som läser datat att OM den försöker läsa data samtidigt som den andra funktionen håller på att lägga in datat så gör den antingen:
1) Läser datat så som det såg ut innan transaktionens början
2) Väntar på att transaktionen arbetar klart och läser sedan datat så som det ser ut efter transaktionens slut

Här har du lite info om hur det fungerar i MySQL: http://dev.mysql.com/doc/refman/5.6/...ansaction.html

Disclaimer: Jag kan inte så mycket om transaction isolation i MySQL, ovan info är baserad på hur databaser brukar fungera + google-fu.

tartareandesire 2015-09-02 08:54

Om tabellen är låst eller inte beror på om du använder MyISAM eller InnoDB. Det kan vara bra att läsa på lite om grunderna i hur de fungerar om du vill förstå vad som händer i din databas.

nim 2015-09-02 09:08

Tabell typen MyISAM låser tabellen vid läsning & skrivning beroende på vad man gör eller vad man själv tycker ( LOCK TABLE t1 WRITE, t2 READ )


I InnoDB är detta borttaget till stordel och istället används row locking ( vilket är modernare ) och enbart drabbar dom rader man arbetar med just nu och medför snabbare datahantering.

tartareandesire 2015-09-02 09:25

Citat:

Ursprungligen postat av nim (Inlägg 20512411)
I InnoDB är detta borttaget till stordel och istället används row locking ( vilket är modernare ) och enbart drabbar dom rader man arbetar med just nu och medför snabbare datahantering.

Nja, InnoDB är inte alltid snabbare.

nim 2015-09-02 09:30

Citat:

Ursprungligen postat av tartareandesire (Inlägg 20512413)
Nja, InnoDB är inte alltid snabbare.

Generellt sätt, jo. Sen om man går djupare så får man välja databas och databasmotor beroende på vad man ska bearbeta.

Men visst, du går säkert och köper en Volvo 740 när vill köra på autobahn.

tartareandesire 2015-09-02 10:12

Citat:

Ursprungligen postat av nim (Inlägg 20512414)
Generellt sätt, jo. Sen om man går djupare så får man välja databas och databasmotor beroende på vad man ska bearbeta.

Men visst, du går säkert och köper en Volvo 740 när vill köra på autobahn.

Det finns inga generella fall :) Som du säger så får man välja lösning efter ändamål precis som med allt annat. Det är få som kör sin bil enbart på Autobahn även om det säkert finns undantag även där :) För den som inte vill, kan eller behöver sätta sig in i vad som är bäst för deras applikation så är InnoDB alltid det rätta valet, det kan jag däremot hålla med om (i de flesta fall annars också men inte alltid som sagt var). Annars blir det lite meningslöst att säga något i stil med att "en bil är snabbare än en båt". Ja, det beror ju på om du ska ta dig fram över vatten eller inte :)

Clarence 2015-09-02 11:19

Citat:

Ursprungligen postat av nim (Inlägg 20512414)
Generellt sätt, jo. Sen om man går djupare så får man välja databas och databasmotor beroende på vad man ska bearbeta.

Generellt sett är MyISAM snabbare än InnoDB för reads. Generellt sett är webbapplikationer övervägande reads. Så oftare än inte kommer MyISAM vara snabbare än InnoDB om man inte ger sig på dumheter eller hög (blandad) last.

Men sen skulle jag ändå generellt sett rekommendera InnoDB/XtraDb/Aria snarare än MyISAM.

Ett exempel på en av många anledningar är TS fråga. Eftersom det finns transaktionsstöd och atomicity i writes så behöver man inte krångla mer än att lägga hela uppdateringen i EN transaktion och därmed alltid få senaste kompletta uppdateringen från sin select.

spyvingen 2015-09-02 15:51

You lost me at MyISAM och InnoDB :)

Jag vill gärna ha en så enkel lösning som möjligt men som klarar av att göra det jag vill.
Jag vill alltid visa förskaste datan men jag vill inte ha den uppdelad om det är så att jag hämtar sidan samtidigt som jag öppnar databasen.

Hur gör man i mysql för att lägga in flera samtidigt?
Ska jag göra flera sqlkommandon och köra in som en enda körning eller måste man tänka på något speciellt.

Är lite noob som ni förstår.
Om jag ska skicka in många samtidigt ska man separera rader med något tecken eller liknande räcker det att göra så här?
Kod:

SQL = "delete from MyTable where field1 = 'XXX'; " & _
      "INSERT INTO MyTable (Field1, Field2) VALUES ('name1', 1);" & _
      "INSERT INTO MyTable (Field1, Field2) VALUES ('name2', 2);"

Kommer detta då gör att allt kommer in på samma gång och om clienten skulle uppdatera så får den snällt vänta till det är klart?

EDIT :
Hittade även detta
Kod:

INSERT
  INTO Table ( Col1, Col2, Col3 )
  VALUES
    ( Value1, Value2, Value3 ),
    ( Value4, Value5, Value6 ),
    ( Value7, Value8, Value9 )

Skulle kanske vara ett ännu bättre alternativ?

Clarence 2015-09-02 16:38

Citat:

Ursprungligen postat av spyvingen (Inlägg 20512421)
You lost me at MyISAM och InnoDB :)

Jag vill gärna ha en så enkel lösning som möjligt men som klarar av att göra det jag vill.
Jag vill alltid visa förskaste datan men jag vill inte ha den uppdelad om det är så att jag hämtar sidan samtidigt som jag öppnar databasen.

Hur gör man i mysql för att lägga in flera samtidigt?
Ska jag göra flera sqlkommandon och köra in som en enda körning eller måste man tänka på något speciellt.

Är lite noob som ni förstår.
Om jag ska skicka in många samtidigt ska man separera rader med något tecken eller liknande räcker det att göra så här?
Kod:

SQL = "delete from MyTable where field1 = 'XXX'; " & _
      "INSERT INTO MyTable (Field1, Field2) VALUES ('name1', 1);" & _
      "INSERT INTO MyTable (Field1, Field2) VALUES ('name2', 2);"

Kommer detta då gör att allt kommer in på samma gång och om clienten skulle uppdatera så får den snällt vänta till det är klart?

EDIT :
Hittade även detta
Kod:

INSERT
  INTO Table ( Col1, Col2, Col3 )
  VALUES
    ( Value1, Value2, Value3 ),
    ( Value4, Value5, Value6 ),
    ( Value7, Value8, Value9 )

Skulle kanske vara ett ännu bättre alternativ?

Det lättaste vore att se till att tabellen är av typen InnoDB (förutsatt att du använder vanilla MySQL, annars kan den heta annorlunda men ändå i princip vara samma motor). Isåfall startar du en transaktion innan du kör din delete query, och avslutar den efter du är klar med dina inserts. På så sätt kommer dina läsningar av datan alltid få senaste avslutade uppdateringen oavsett om din uppdatering precis har tagit bort massa rader och ännu inte hunnit lägga in något så kommer det synas först när transaktionen är avslutad (committad).

Byt till InnoDB:
Kod:

ALTER TABLE table_name ENGINE=InnoDB;
Uppdatering pseudo-kod (använder du verkligen VB!?!):
Kod:

Db->beginTransaction()
// Alla db queries
Db->commitTransaction()

Därefter syns resultatet inte förräns allt mellan begin och commit är färdigt, under tiden kommer det (normalt sett) den uppdaterade datan endast vara synlig för processen/transaktionen själv.

spyvingen 2015-09-03 08:02

Kollade databasen nu och den är redan InnoDB

Ja jag kör ASP Klassiskt för det är det enda jag kan :) Och har inte direkt tid att lära mig nått nått även om jag vill :)

Förstår inte din pseudo-kod kod riktigt.
Snackar vi mysql eller VB/ASP

Och vilket av förslagen jag gav bör jag använda en enda insert med massa olika rader i eller en insert per rad.


Om jag förstår det hela rätt nu så bör min mysql se ut något i stil med detta?
Rätta mig om jag har fel.
Kod:

begin;
INSERT INTO Table ( Col1, Col2, Col3 ) VALUES ( Value1, Value2, Value3 ), ( Value4, value5, Value6 ), ( Value7, Value8, Value9 );
Commit;

Och jag lägger alla mina rader i en och samma insert för det låter som det är effektivast istället för att göra massa inserts?

Clarence 2015-09-03 10:10

Citat:

Ursprungligen postat av spyvingen (Inlägg 20512431)
Kollade databasen nu och den är redan InnoDB

Ja jag kör ASP Klassiskt för det är det enda jag kan :) Och har inte direkt tid att lära mig nått nått även om jag vill :)

Förstår inte din pseudo-kod kod riktigt.
Snackar vi mysql eller VB/ASP

Och vilket av förslagen jag gav bör jag använda en enda insert med massa olika rader i eller en insert per rad.


Om jag förstår det hela rätt nu så bör min mysql se ut något i stil med detta?
Rätta mig om jag har fel.
Kod:

begin;
INSERT INTO Table ( Col1, Col2, Col3 ) VALUES ( Value1, Value2, Value3 ), ( Value4, value5, Value6 ), ( Value7, Value8, Value9 );
Commit;

Och jag lägger alla mina rader i en och samma insert för det låter som det är effektivast istället för att göra massa inserts?

Din SQL ser ok ut. Normalt sett använder man funktioner i programmeringsspråket (och jag var inte ens säker på vilket språk du använde, hence pseudo-kod) för transaktionsbiten vilket t ex gör att man programmatiskt kan rollbacka/committa beroende på resultat av frågor.

Att lägga till många rader i ett statement är snabbare, upp till någon punkt mellan 100 och 10 000 rader beroende på omständigheterna. Det har heller ingen nämnvärd risk att ställa till jobbiga problem så länge du inte använder MyISAM.

spyvingen 2015-09-03 11:12

Ok då är jag med på pseudo visste inte riktigt bar aom det var sql du prattade om eller om det var programmatiskt men det jag skrivit ovan kommer läsa in allt i db:n och när allt väl är där så trycker den igenom förändringen på direkten.

Antar att min delete även ska ligga mellan begin och commit kom jag på i efterhand men då kunde jag inte redigera.

antalet rader är minimalt men från 0 upp till 50-60 så själva sql delen är väl minimal i tid och det som faktiskt tar tid är mina sidhämtningar.

Clarence 2015-09-03 22:01

Citat:

Ursprungligen postat av spyvingen (Inlägg 20512437)
Ok då är jag med på pseudo visste inte riktigt bar aom det var sql du prattade om eller om det var programmatiskt men det jag skrivit ovan kommer läsa in allt i db:n och när allt väl är där så trycker den igenom förändringen på direkten.

Antar att min delete även ska ligga mellan begin och commit kom jag på i efterhand men då kunde jag inte redigera.

antalet rader är minimalt men från 0 upp till 50-60 så själva sql delen är väl minimal i tid och det som faktiskt tar tid är mina sidhämtningar.

Pseudo-kod skrivs för det mesta för att man ska kunna reproducera koden i sitt eget språk utan att själva instruktionen kräver att man kan något specifikt språk (även om viss funktionalitet ändå kräver att man kan något inom en grupp av språk).

Och ja, din delete ska absolut ligga mellan starten och commiten av transaktionen.

Menar du 50-60 sekunder? Isåfall föreslår jag att du låter scriptet hämta datan först och sen ansluter till databasen och lägger in datan i en endaste select. Utifall att scriptet hänger sig kan det annars vara så att du inte har en bra idle timeout mot databasen (för jag antar att du inte har kontroll över databasserverns inställningar?) vilket kan orsaka problem. Är det ingen viktig/populär sajt kan du förvisso skippa det och hoppas att det funkar och ändra det först om det faktiskt blir ett problem.

Annars är code for failure en bra praktik. Allt som kan lägga av kommer förr eller senare göra det, spelar det då någon roll? Vad händer om 3e part du hämtar data från går ner? Vad händer om din databasserver går ner? Vad händer när du får deadlocks på db transaktionerna? Vad händer när du har en bugg i din datahämtning som gör att scriptet kör in i oändligheten? Men som sagt, detta kan vara överkurs i ditt fall.

spyvingen 2015-09-04 12:44

50 - 60 då menar jag bara poster i databasen som ska läggas in.
Scriptet tar 1-4 sekunder att köra typ.

Det är inte många som ska använda den kanske 20-30 pers. I allra värsta fall upp emot 80 pers men det kommer mest troligt inte hända :)

Räkna in alla möjliga fel är inget jag orkar lägga tid på i detta projekt blir det ett fel så får nån rapportera det så får jag kika på det bara :)

Tror jag kommer göra som du skriver samla in allt från de olika sidorna och sedan kör jag in allt i db:n på slutet. Även om sidan inte tar så lång tid att ladda nu så kommer den sedan hämta från ytterligare källor så det kommer ju ta längre tid senare.


Alla tider är GMT +2. Klockan är nu 04:46.

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