16. juli 2009 - 01:01Der er
12 kommentarer og 1 løsning
Frigøre memory
Jeg har en Java-applikation kørende, som i døgndrift skriver nye rækker til en MySQL-tabel vha. JDBC. Der foretages derudover kun meget få queries mod tabellen for at sikre, at data lagres korrekt.
Så længe applikationen kører, stiger memory-forbruget til mysqld-nt støt og roligt. Jeg har haft forskellige out-of-memory problemer, som er løst ved 1) opgradering til nyeste MySQL-version, 2) tilretning af my.ini og - måske unødvendigt - 3) skrivning til mindre work-tabel, som senere kopieres til stor master-tabel.
For helt at undgå memory-problemer har jeg et ønske om at frigøre memory. Dette sker pt. ved genstart af MySQL, men mit spm. er, om det er muligt at frigøre memory uden genstart. Jeg anvender kun innodb-tabeller.
'reset' og 'flush' er grundlæggende samme funktionalitet, som jeg forstår det, og ingen af dem har effekt her - måske fordi der er tale om innodb-tabeller (?)
Med mit nuværende setup er der ret langt op til limit, som ikke nås før efter måske 2-3 ugers uafbrudt og uforstyrret drift. Hvis jeg dog foretager en 'stor' query undervejs, vil limit nås ret hurtigt. Limit for mysqld-nt er ca. 1.153.000 KB, kan jeg se. Fejl i den forbindelse er 'long semaphore wait', som vist er en relativ hyppig MySQL-fejl.
Både 'flush' og 'reset' returnerer umiddelbart uden fejl, men memory frigøres ikke.
Frigør statements, hvad mener du præcis med det? Jeg tilgår databasen med et Java-program, hvor jeg (ved hver opdatering) åbner en connection, som jeg lukker igen osv. Mener at det helt standard.
SHOW VARIABLES LIKE 'query%' giver i mit tilfælde: query_alloc_block_size 8192 query_cache_limit 1048576 query_cache_min_res_unit 4096 query_cache_size 0 query_cache_type ON query_cache_wlock_invalidate OFF query_prealloc_size 8192
Skrivning til mindre work-tabel, som senere kopieres til master-tabel har generelt stor virkning på memory-forbruget. Denne løsning er dog kun mulig, når man som jeg ikke har brug for at foretage queries mod data i master-tabellen men kun mod data i work-tabellen - altså hvor master-tabellen blot er et inaktivt data-lager.
Det grundlæggende ønske om at frigøre memory uden genstart af MySQL har jeg ikke kunnet løse, men jeg har lavet en Java-løsning, hvor MySQL kan genstartes uden tab af data. Løsningen tager også hånd om den situation, hvor MySQL er optaget af noget andet, f.eks. intern oprydning, som jeg har observeret fra tid til anden. Løsningen er lavet således: Alle skrivninger til databasen afvikles i selvstændige tråde. En tråd venter på flg. måde: 1. Hvis MySQL er afbrudt inden skrivning, loop'es i tråden indtil DriverManager.getConnection() accepteres. 2. Hvis MySQL afbrydes eller er optaget af noget andet, f.eks. intern oprydning, efter connection er accepteret men under skrivning, vil PreparedStatement.executeUpdate() blokere. 3. For at sikre at antallet af connections begrænses er etableret en BlockingQueue, som trådene skal igennem. Herved er der ikke noget loft over antallet af tråde, idet trådene blot vil vente på, at BlockingQueue ikke blokerer længere, inden DriverManager.getConnection() forsøges. 4. Timestamp defineres så snart en tråd kaldes og er derved uafhængig af, at skrivning fysisk måske først sker på et senere tidspunkt.
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.