01. august 2000 - 17:28Der er
24 kommentarer og 1 løsning
Browser timer out - HAASTEER
Hej alle i kloge hovder :
Jeg har et skrækkeligt problem jeg håber nogen kan hjælpe mig med.....
Jeg har lavet en webside der skal hente poster ind fra en SQL database, den skal herefter gemme evt. ændringer som brugeren måtte have. Siden fungerede fint da databasen bestod af 10 poster, men den skal virke på en base der er over 300.000 poster stor. Da jeg havde lagt 23.000 poster ind i basen, kunne jeg ikke åbne mere end 3 poster, ved den fjerde post timer browseren ud. Nu har jeg prøvet at gøre basen mindre så den er på 3.000 men nu har jeg mulighed for at åbne 50 poster, hvor nr. 51 så timer ud. Jeg henter poster ved hjælp af nogle SQL sætninger, og hvis der er flere poster så gennemløber jeg det recordset de ligger i for at finde den rigtige post.
Siden ligge på en webserver og databasen ligger på en SQL server (6.5), forbindelsen laves vha. en system DSN.
Jeg har kørt en trace på aktiviteten mod Database serveren, og den viser at der mange gange (næsten efter hver gang der er blevet hentet en post) køres flg. SQL sætning :
SELECT * FROM myTabel
MEN DENNE SÆTNING HAR JEG IKKE I MIN KODE !!!!! OG DEN KØRES AF DEN BRUGER SOM JEG ER BLEVET OPRETTET TIL PÅ SQL SERVEREN ???????
Det er også efter sådan en sætning at browseren timer ud. Er der et resource forbrug som jeg ikke er klar over, bliver alle records gemt et eller andet mystisk sted....
Der kan være bunkevis af grunde til at din app ikke scalerer ordentligt.
Lukker du alle dine recordsets og connections? Laver du for mange loops hvor du bygger strenge? Bruger du option explicit så du skal erklære alle dine variabler? Har du et dictionary object gemt i en application variabel? Gemmer du objekter i session eller application variabler i det hele taget? Har du indekseret de væsentligste kolonner i din DB? Hvilken udgave af MDAC bruger du (2.1 var dårlig) Jeg kunne blive ved og ved...
BTW: OLE DB er hurtigere og mere effektivt end at bruge en DSN via ODBC.
jette >> nej jeg har måske forklaret mig dårligt, once again for the record : Jeg henter en post frem adgangen og viser data på min side, her har man mulighed for at ændre på data. Man klikker så næste og posten bliver opdateret i DB, med de ændringer man havde fortaget. Når jeg gør det igen og igen indtil jeg har gjort det 50 gange, så timer den ud.
tigerdyr >> Jeg har nok mellem 40-43 kolonner ( jeg har det på mit arbejde så undskyld det lidt usikre antal), og det er sådan at jeg skal køre mindst 1 og maks 5 SQL sætninger af alt efter om de returnere den post jeg skal bruge : f.eks. så skal jeg først se om der er en post der er planlagt til at blive hentet, hvis der ikke er det så skal man f.eks. se om der er nogen der har været hentet før, men som skal hentes igen på grund af bla.bla.bla. osv.osv. Hvis der ingen planlagte poster er så skal den hente den næste ubehandlet post i basen, og det gør jeg f.eks. således :
SELECT * from mytabel where ID = (SELECT Min(Id) from mytabel where optaget =\'0\') Den skulle så gerne hente den den post med mindste foreløbige ID og som ikke er behandlet endnu. ( Det fungere fint, jeg har forsøgt med en forspøgsel og den returnede korrekt )
ricardo >> Jeg tror måske at det er et problem at jeg ikke får lukket mine recordsets, men når jeg forsøger, så får jeg en fejlmedl. der siger at den handling er ulovlig hvis recordsettet er lukket !!!!
ALLE >> Er der nogen der kan lure hvorfor den x-tra sætning kommer, er det noget internt i SQL eller er det noget en DSN kan finde på.....
OK, det bliver nok først imorgen, da jeg som sagt skal hente den på jobbet. Men anyway så har du garanteret ret i at den er fejlkonstrueret, men jeg er også lidt ny i faget. Vil du have hele koden eller kun der hvor jeg regner med der er fejl...-> Der hvor timeoutet forekommer ALtså når jeg henter poster og opdatere.....
P.S. Der er nok over 1000 linier kode, men der hvor problemer er nok en 100 - 150...
->ropotten: Jeg tror, udfa de oplysninger som du her har givet, at fortælle hvad fejlen kan være.
personligt har jeg aldrig været ude for at SQL server selv udfører den slag forespørgsler...
Jeg vil derfor foreslå dig følgende:
1) check at der ikke er triggere på din tabel, for den sags skyld - alle de tabber du bruger der kan forårsage en select *
2) Gå din ASP Kode igenne og udskriv strSQL konsekvent før du kalder conn.execute.
mit bedste bud på en fejl er at det er i 2) det går galt, den slag sker nemt hvis du f.eks. genbruger en streng så der kommer til at stå to select udtryk i den samme streng du giver til din conection.
Her er scriptet fra siden der henter poster ind fra basen.....
-------------------------------------------------------------------- <% \'Forbindelse åbnes Dim objConn Dim objRec Dim objRecL
Set objConn = Server.CreateObject (\"ADODB.Connection\") Set objRec = Server.CreateObject (\"ADODB.Recordset\") Set objRecL = Server.CreateObject (\"ADODB.Recordset\")
Function opdateVars() \' Her opdateres variable .... emnenr = objRecf(\"ID\") Session(\"emnenr\") = emnenr telefon = objRecf(\"Telefon\") .... End Function
Function NullVars() \' her nul stilles variable .... emnenr = \"\" Session(\"emnenr\") = emnenr telefon = \"\" .... End Function
firstSQL = \"SELECT * FROM mytabel WHERE Bruger = \'\" & Session(\"Bruger\") & \"AFT\' AND\" firstSQL = firstSQL & \" Afgørelse LIKE \'A\'\"
secondSQL = \"SELECT * FROM mytabel WHERE Bruger <> \'\" & Session(\"Bruger\") & \"AFT\' AND\" secondSQL = secondSQL & \" Afgørelse LIKE \'A\'\"
theirdSQL = \"SELECT * FROM mytabel WHERE Afgørelse LIKE \'OP\'\"
fourthSQL = \"SELECT * FROM mytabel WHERE Afgørelse LIKE \'IS\' AND Bruger = \'ingen_svare\'\"
endSQL = \"SELECT * From mytabel where ID = (SELECT Min (Id) FROM mytabel WHERE Bruger = \'0\' AND postnr >\" & post1 &\" AND postnr < \" & post2 & \")\"
dim tidTimer, tidRing, tidDato Application.Lock \' Denne rutine er nok lidt kloset lavet, men jeg ideen er at først køres \' firstSQL. Hvis recorsettet ikke er tomt så skal hver post i settet \' kontrollere om det tidspunkt der står i variablen tilring er er gyldigt \' hvis den er det skal posten markeres som optaget og do løkken skal slutte. \' Hvis en post blev fundet er NullVars ikke kørt og emnenr indeholder en værdi og \' der udføres ikke flere SQL sætninger. Hvis en post ikke blev fundet er emnenr tom \' og næste SQL sætning udføres. Sådan køre det helt igennem til endSQL....
Set objRecf = objConn.Execute(firstSQL) If NOT objRecf.EOF Then \'Match emner med aftale
Do While Not objRecf.EOF opdateVars() tidTimer = TimeValue(tilring) startminut = DateAdd(\"n\", -1, tidTimer) slutminut = DateAdd(\"n\", 120, tidTimer) if (Time > startminut AND Time < slutminut) Then objConn.execute(\"update mytabel set bruger = \'opt\' where ID =\" & objRecf(\"ID\")) Exit Do else objRecf.MoveNext End if
NullVars()
Loop objRecf.Close Set objRecf = Nothing End if
If (emnenr = \"\") Then Set objRecf = objConn.Execute(secondSQL)
If NOT objRecf.EOF Then \'Match
Do While Not objRecf.EOF opdateVars() tidTimer = TimeValue(tilring) startminut = DateAdd(\"n\", 15, tidTimer) if (Time > startminut) Then
objConn.execute(\"update mytabel set bruger = \'opt\' where ID =\" & objRecf(\"ID\"))
Exit Do else objRecf.MoveNext End if \'objRecf.Move NullVars()
Loop objRecf.Close Set objRecf = Nothing
End if
If (emnenr = \"\") Then
Set objRecf = objConn.Execute(theirdSQL)
If NOT objRecf.EOF Then \'Match
Do While Not objRecf.EOF opdateVars() tidDato = DateValue(datoen) Dim Datoe,Ddag,Dmdr,Daar,idag Ddag = DatePart(\"d\", Date) Dmdr = DatePart(\"m\", Date) Daar = DatePart(\"yyyy\", Date) idag = Ddag & \"/\" & Dmdr & \"/\" & Daar Datoe = DateValue(idag)
if (Datoe > tidDato) Then
objConn.execute(\"update mytabel set bruger = \'opt\' where ID =\" & objRecf(\"ID\"))
Exit Do else objRecf.MoveNext End if \'objRecf.Move NullVars()
Loop objRecf.Close Set objRecf = Nothing End If
If (emnenr = \"\") Then Set objRecf = objConn.Execute(fourthSQL)
If NOT objRecf.EOF Then \'Match
Do While Not objRecf.EOF opdateVars() tidDato = DateValue(datoen)
objConn.execute(\"update mytabel set bruger = \'opt\' where ID =\" & objRecf(\"ID\"))
Exit Do else objRecf.MoveNext End if \'objRecf.Move NullVars()
Loop objRecf.Close Set objRecf = Nothing
End If
\' endSQL skal bare hente næste ubehandlede post ind i basen.
If (emnenr = \"\") Then Set objRecf = objConn.Execute(endSQL)
If NOT objRecf.EOF Then \'Match opdateVars() objConn.execute(\"update mytabel set bruger = \'opt\' where ID =\" & objRecf(\"ID\")) \' DET ER HER DET GÅR GALT NR. 51 GANG SIDEN LOADES IND....
ELSE NullVars() tomDB = \"<BR><BR><BR><BR><BR><BR><BR><BR><BR><H3>INGEN POSTER TILBAGE I DATABASEN - KONTAKT SUPERVISOR</H3><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR>\" move = \"0\"
objRecf.Close Set objRecf = Nothing
End If End If
End If End If
End If
Application.Unlock
\'Forbindelse nedlægges
\'objConn.Close() \'Set objConn = Nothing
%> ------------------------------------------------------------- Her er scriptet fra siden der opdatere basen:
saveSQL = \"SELECT * FROM mytabel WHERE ID = \" & nemnenr
Application.Lock
Set objRecEmne = objNewCon.Execute(saveSQL) If NOT objRecEmne.EOF Then \'Match
If nUdfald = \"E\" Then
objNewCon.execute(upSQLEJ)
Else If nUdfald = \"S\" Then
objNewCon.execute(upSQLS)
Else If nUdfald = \"IS\" Then
objNewCon.execute(upSQLIS)
Else If nUdfald = \"I\" Then
objNewCon.execute(upSQLI)
Else If nUdfald = \"A\" Then
objNewCon.execute(upSQLA)
Else If nUdfald = \"K\" Then
objNewCon.execute(upSQLK)
Else If nUdfald = \"O\" Then
objNewCon.execute(upSQLO)
Else If nUdfald = \"OP\" Then
objNewCon.execute(upSQLOP)
Else \' Hvis intet blev valgt så skal Set objRecEmne = objNewCon.Execute(\"update mytabel set bruger = \'0\' where ID =\" & objRecEmne(\"ID\")) End If End If End If End If End If End If End If
Jeg kan ikke se hvorfor du har \" & \" inde alle mulige steder - det behøver du ikke...
Når du skal sætte en variabel ind i en SQL-streng så markerer du med \" - og derefter et &-tegn - derefter skriver du varibel navnet ! - efterfulgt af et &-tegn og dobbeltpling (\")
Men når du skriver \" - efter (\" &) - så sker der jo ikke noget....
Du skaber recordset objekter som du ikke bruger og det er en sikker opskrift på at køre din server nede. Væk med dem!
Dine mange \"if dit then dat\" kunne snildt erstattes af en enkel SELECT CASE. Det andet er noget rod. Du kunne også migrere dine SQL strenge over i dine \"ifs\", så slipper du for at serveren kører den krævende proces det er, at bygge en streng op med \"&\". Du gør det med samtlige uanset hvilken af dem der skal bruges. Byg kun det du skal bruge når du skal bruge den og ikke før.
Dine funktioner er faktisk subroutines: en funktion returnere en enkel variable med samme navn som funktionen, mens en sub er en stump kode der køres der, hvor du kalder den. Jeg tror ikke de virker: post koden.
Jeg kan heller ikke se hvorfor du absolut skal låse applicationen...?
Jeg låser applicationen, således at to brugere ikke kan hente samme post ind på samme tid, men det er måske ikke nødvendigt ???
Mine funktioner er næsten identiske med dem jeg har postet, der er bare flere variabler der får tildelt en værdi, og det ser altså ud som om at de virker !!!??
Hvor er det lige jeg skaber recordsets som jeg ikke bruger ??
tigerdyr >> Jeg skal bruge emnenr mange gange så derfor lægger jeg også værdien i en variabel....
jette >> det du siger jeg skal gøre virker ikke !!!
GENERELT >> Jeg kom til at tænke på at jeg jo åbner en connection for hver gang en side læses ind, kan det være et problem og kan det evt. løses ved at lægge forbindelsen ind i Application on_start proceduren, og nedlukkelsen af forbindelsen i Applikation on_end proceduren, også lade alle der er logget ind bruge den samme connection ????
>> Hvor er det lige jeg skaber recordsets som jeg ikke bruger ??
Jeg kan ikke se hvor du bruger objRec og objRecL. Men de er skabt i toppen.
>> to brugere ikke kan hente samme post ind på samme tid
Det virker ikke - og en row er låst mens den bliver hentet, og mens du skriver til den, og ellers ikke.
>> Mine funktioner er næsten identiske med dem jeg har postet
En funktion returnerer een værdi og den skal have samme navn som funktionen.
det her:
function DoMyVars()
dit = \"blip\" dat = \"blop\" dut = \"båt\"
end function
virker ikke, tro mig. Du må have \"on error resume next\" et eller andet sted, ellers ville den give en error.
sub DoMyVars()
dit = \"blip\" dat = \"blop\" dut = \"båt\"
end sub
virker. En sub (en række kommandoer eller whatever) skal kaldes uden parenteser eller som
call MySub(arg1,arg2)
hvis du forstår.
>> at lægge forbindelsen ind i Application on_start proceduren
Nej, nej og atter nej!
Gem aldrig en connection objekt i en application variabel! En connection streng går an, men ALDRIG en connection object. Gør du det, tvinger du samtlige bruger i en kø, hvor connection skal være frigivet fra den første før den næste kan bruge den! Det er en særdeles dårlig ide og kan være årsag til hele miseren.
Connection Pooling passer godt på connections - faktisk kan det nogen gange betale sig at lade være med at lukke dem, da andre brugere \"arver\" åbne connections pr. automatik.
>> Det virker ikke - og en row er låst mens den bliver hentet, og mens du skriver til den, og ellers ikke.
Det er måske ikke nødvendigt at låse app, men jeg opdatere bruger navnet til \'opt\', hvilket medføre at ingen andre henter posten ind.
>> virker ikke, tro mig. Du må have \"on error resume next\" et eller andet sted, ellers ville den give en error.
Det er ikke for at lede nogen på vildspor eller snyde nogen, men jeg har ikke nogen \"on error resume next\", jeg har heller ikke nogen return blipblopbåt, OG mine variable bliver opdateret eller nulstillet ved kald til funktionerne, men hvis det kan foresage rav i logikken, så må jeg hellere lave dem om til subroutines....
Er der noget sted man kan læse lidt om connection pooling, for det lyder som en go ide, da jeg også kan se på min trace udskrift at en stor del af transaktionerne er oprettelse og nedlukning af forbindelser.....
Sidaste punkt på dagsordnen, kan det at jeg opretter nogen recordset\'s som jeg ikke bruger eller får lukket, være oversag til den mærkelige SQL-streng :
Hvis du vil låse som du beskriver, skal du låse den inden du laver din connection - ellers kan andre komme til. Det er faktisk din connection der skal låses.
Jeg tror du skal være mindre ambitiøs: først kravle, siden gå.
OK, det er taget til efterretning, men anyway så hjalp det at jeg slettede de recordsets som jeg ikke brugte, så mange tak for hjælpen...
Synes godt om
Ny brugerNybegynder
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.