Jag har under den senaste månaden jobbat på en webbsajt som ska ligga på ett konto på webbhotellet Loopia. Jag gillar verkligen Loopia, de har bra support, schyssta priser/tjänster och är trevliga att ha att göra med. Tidigare har jag mest kodat webb i PHP, men eftersom jag numera enbart sysslar med .NET i mitt vanliga jobb tänkte jag att det är lika bra att jag kör på med en teknik även på min egna tid. Man lär sig ju grejer hela tiden, och det känns effektivast att koncentrera sig på ett spår i taget.
Hursomhelst! Från och med version 5 finns det stöd för stored procedures i MySQL. Och MySQL har till och med varit så vänliga att de utvecklat en ADO.NET-provider som är specialanpassad för kommunikation just mellan .NET-applikationer och MySQL-databaser. Loopia tillhandahåller den senaste versionen av denna komponent på sina servrar. Bra förutsättningar för att utveckla seriösa webbapplikationer av medelstorlek alltså.
När jag utvecklat den här webbplatsen har jag kört den lokalt och låtit den gå mot min egen Loopia-databas. Det har funkat mycket bra och har fördelen att jag kunnat sätta upp en testsajt på mitt Loopia-konto också, med samma databas, som jag kunnat låta valda personer ha tillgång till.
Nu inför lanseringen av webbplatsen laddade jag upp den till det Loopia-konto där den ska ligga, satte upp databastabeller och stored procedures i kontots databas och tänkte att det borde funka smärtfritt från början just eftersom det är samma webbhotell och funkat så bra innan. Där bedrog jag mig!
När man gick in på en sida som anropar en stored procedure möttes man av följande glada meddelande från MySQL Connector/NET:
Unable to retrieve stored procedure metadata. Either grant SELECT privilege to mysql.proc for this user or use ”use procedure bodies=false” with your connection string.
Vad var nu detta? Jag hade ju skapat en databasanvändare speciellt för webbapplikationen, med precis de rättigheter som ska behövas. Och det kunde inte vara något fel på applikations- eller stored procedure-koden, för det hade ju funkat fint i utvecklingsmiljön, som är mycket lik produktionsmiljön.
Efter att ha bankat huvudet i väggen en stund gick jag in och tittade på ROUTINES-tabellen i information_schema-databasen som hör till varje MySQL-databas. Där kunde jag se att mina stored procedures fanns upplagda korrekt, att det var ett särskilt administrationskonto som skapat dem – ett konto som jag själv lagt upp just för detta – och även att något som heter SECURITY_TYPE var satt till ”DEFINER” på samtliga stored procedures. Det sistnämnda verkade intressant! Efter ett par snabba tester kunde jag konstatera följande:
I Loopias MySQL-konfiguration är det endast den databasanvändare som skapade stored procedure:n som kan exekvera den.
Är det smart eller bara irriterande? Jag är nog inte rätt person att bedöma det, men jag vet att det tog en stund för mig att lista ut det.
Uppdatering: Felmeddelandet jag fick ovan antydde att man kunde lösa det genom att ge SELECT-rättigheter för tabellen mysql.proc till aktuell användare, alternativt använda parametern use procedure bodies=false i sin connectionstring. Eftersom man sällan har möjlighet att dela ut godtyckliga rättigheter till höger och vänster om man använder ett webbhotell så testade jag det andra alternativet. Och det funkade! Det man måste tänka på då är att alla parametrar man skickar in till sina stored procedures måste anges i rätt ordning (alltså den ordning som stored procedure:n förväntar sig dem) och med rätt datatyp. Detta eftersom man helt går förbi den kontroll av parametrarna som annars görs av MySQL med hjälp av tabellen mysql.proc.
En annan lurig grej med Loopia har att göra med omstarter av ASP.NET-applikationer. I normala fall håller ASP.NET koll på om de filer som ingår i en webbapplikation ändras, varpå applikationen startas om så att ändringarna blir verksamma. Det kan handla om allt ifrån en ny version av källkoden till en enkel justering av ett parametervärde i en konfigurationsfil. Att hela denna apparat är nödvändig har att göra med att en ASP.NET-sajt faktiskt är kompilerad kod, till skillnad från exempelvis en PHP-lösning, där det rör sig om script som parsas när de efterfrågas. I normala fall fungerar det hursomhelst bra, även om själva omstarten/kompileringen av applikationen oftast innebär att besökaren/användaren får sitta och vänta några extra sekunder vid just det anropet.
Men på Loopia fungerar det inte så här. Enligt dem själva använder de en stor NAS där allt kundmaterial ligger – alltså alla webbapplikationer. Tydligen är den filstrukturen för omfattande för att ASP.NET ska kunna övervaka alla ändringar som görs (låter inte helt ologiskt), vilket rent funktionellt inneb¤r att den här omladdningsfunktionen helt är satt ur spel. Som ett alternativ finns det en automatiskt recycle-process som körs ungefär var 26:e timme, då applikationerna laddas om oavsett om det egentligen behövs eller inte.
Men det duger ju inte om man sitter och utvecklar eller testar en sajt! Vadå, ska man ladda upp filerna, konstatera att man råkat missa en inställning i Web.config och sedan vänta i upp till 26 timmar på att en korrigerad version ska börja användas av sajten? Det är naturligtvis helt ohållbart.
För att försöka lindra frustrationen har Loopia utvecklat en funktion i den kontrollpanel som man som kund har tillgång till där man manuellt kan begära en omladdning. En enkel knapptryckning så läses de aktuella versionerna av filerna in i minnet. På Loopias supportforum står det:
”…i Loopia Kundzon kan du själv begära att ASP.NET-applikationen ska laddas om, exempelvis efter att du gjort en ändring.”
Då är ju allt bra! Eller är det? När jag har använt funktionen har jag ofta upplevt ett märkligt beteende hos applikationen. Ibland laddas den verkligen om och får de senaste uppdateringarna, men om man sedan startar om den igen så kan den gå tillbaka till en gammal version. Och ibland verkar ingenting alls hända. Trots att det mycket tydligt står i kontrollpanelen att ”applikationen startades om med ett lyckat resultat”.
Efter korrespondens med Loopia har de bekräftat att funktionen inte alls fungerar som det står på supportsidorna. I verkligheten fungerar den bara en gång per recycle-intervall, vilket alltså betyder att man kan använda den en gång var 26:e timme. Jag kan alltså som mest uppdatera mina webbapplikationer två gånger per dygn, ungefär. Vilken lyx!
Loopia hävdar att de jobbar på att få fram en mer hållbar lösning på detta problem, men att det inte finns något datum för när det ska vara klart. Vilket betyder att de lika gärna kunde säga att man får leva med det system som finns idag.