MyISAM är en mycket vanlig lagringsmotor att använda sig när man skapar tabeller i MySQL och jag använder den själv väldigt mycket. MyISAM fungerar oftast väldigt bra till de flesta applikationer men har vissa nackdelar jämfört mot andra lagringsmotorer. Avsaknaden till radlåsning och att tabellåsning sker vid infogning av data är något som ofta nämns.
MyISAM har dock möjligheten att skriva data även om en eller flera lås för att läsa data har satts på tabellen.
När du skriver och läser data kommer tabellen att låsas. En tabell kan ha flera samtidiga låsningar för läsning men endast ett lås för skrivning. Inget läslås kan heller sättas om ett befintligt skrivlås är satt. Detta medför att om ett skrivlås ska sättas så måste MySQL vänta på att alla läsningar slutförs innan skrivlåset kan sättas. På så sätt är det lätt att tro att om en tabell har väldigt många läsningar så kan det ta tid innan data får skrivas till tabellen. Men detta är en sanning med modifikation.
För alla skrivningar till tabellen förutom INSERT satsen gäller detta. MyISAM har alltså möjligheten att samtidigt som läsningar av tabellen pågår så kan den lägga till data i slutet på tabellen. Så fort du ska ta bort data eller modifiera data i tabellen så måste hela tabellen låsas för skrivning eftersom detta sker i redan befintlig data.
När du tar bort data så lämnar du även ett hål i tabellen som MySQL kommer försöka fylla igen nästa gång data sätts in. Normalt sätt behöver inte hela tabellen låsas för INSERT men om där finns hål i tabellen efter borttagna rader så kommer MySQL att vänta med att lägga in data tills ett skrivlås kan sättas. I vissa fall kan detta vara ett problem men går att lösa genom att ändra inställningsvariabeln concurrent_insert.
Variabeln concurrent_insert kan ha ett värde av 0, 1 eller 2. Som standard är värdet satt till 1 vilket gör att lagringsmotorn beter sig enligt ovan – alltså väntar på skrivlås om det finns hål att fylla i tabellen. Om värdet sätts till 0 så stängs funktionen av och INSERT måste alltid vänta på skrivlås. Om värdet sätts till 2 så kommer skrivningar till slutet av tabellen att tillåtas även om det finns hål att fylla i tabellen.
En tabell där data ständigt läggs till och tas bort kan bli onödigt stor om man inte fyller igen hålen i tabellen. Så att modifiera den variabeln bör endast göras om du verkligen är medveten om vad det innebär för dig. Det är också högst troligt att du inte kommer kunna genomföra denna ändring på ett vanligt webbhotell utan är endast aktuellt för dig med full kontroll på servern.
Varning för dig som har binära loggfiler aktiverat
Det är inte ovanligt att binära loggfiler är aktiverat i MySQL då detta är ett krav för en masterserver ska kunna återskapa en exakt kopia av innehållet på en slavserver och loggen ger även bättre möjlighet att återskapa förlorad data på servern.
Om binära loggfiler är aktiverat och du försöka sätta in data i tbl1 från tbl2 med INSERT … SELECT så kommer tbl2 att låsas för skrivning trots att tabellen endast används för läsning. Är binära loggfiler avstängt kommer dock bara tbl2 att låsas för läsning istället vilket gör att ny data kan sättas in i slutet och andra läsningar ske från tabellen.
Detta kan skapa problem och låsning av webbapplikationer om både läsningar och skrivningar ska vänta på att en större INSERT … SELECT ska exekveras klart.
Det finns ett par lösningar på detta men förmodligen är det smartast att sätta sig ner och se över sin databasdesign och fundera på alternativa metoder för att uppnå samma sak.