torsdag 10 juli 2008

Veckans kod...

Har gjort ett antal webb applikationer med .net & mysql under senaste året. Av nån anledning verkar ado.net & mysql inte riktigt vara överens vad gäller connection poolingen och emellanåt droppas vissa referenser till connections. Har gjort en hel del tester kring detta eftersom det i första hand brukar uppstå när en connection inte stängs efter en reader t ex. Problemet verkar ligga utanför koddelen enligt testresultaten i alla fall.
Funderade ett bra tag på en lösning och kom fram till att jag borde läsa på lite mer om mysql. Resultatet blev att jag skrev ett litet skript som man kan köra på t ex schemaläggning eller t o m vid varje page load om man vill. Hittills inte implementerat det skarpt i något projekt men troligtvis åker det in i ett under kommande vecka (som är den fjärde veckan av min semester som jag jobbar)

Exempelkod i C# / .Net 2.0 med SubSonic som DAL
// Usage
int[] killedConnections = KillOldConnectionPool(50);
litKilled.Text = "Killed " + killedConnections[0].ToString() + " of " + killedConnections[1].ToString() + " connections";
// Kills connections and returns numKilled/numTotal
private int[] KillOldConnectionPool(int maxConnectionTime)
{
QueryCommand cmd = new QueryCommand("show processlist");
ArrayList processesToKill = new ArrayList();
IDataReader r = DataService.GetReader(cmd);
int poolcount = 0;
while (r.Read())
{
int pID = Convert.ToInt32(r["Id"].ToString());
string state = r["Command"].ToString();
int time = Convert.ToInt32(r["Time"].ToString());
if (state == "Sleep" && time >= maxConnectionTime && pID > 0)
{
processesToKill.Add(pID);
}
if(pID > 0)
poolcount++;
}
r.Close();
foreach (int pId in processesToKill)
{
try
{
cmd.CommandSql = "kill " + pId.ToString();
DataService.ExecuteQuery(cmd);
}
catch (Exception ex){}
}
int[] ret = new int[2];
ret[0] = processesToKill.Count;
ret[1] = poolcount;
return ret;
}

Inga kommentarer: