Wednesday, April 14, 2010

Which sql query you think is the worst for disks ...

Based on milek.blogspot.com

#!/usr/sbin/dtrace -qs

#pragma D option strsize=8192


pid$3::*mysql_parse*:entry
{
self->a=1;
self->query=copyinstr(arg1);
self->count=0;

}

pid$3::*mysql_parse*:return
/ self->a && self->count > $2 /
{
printf(\"### write() count: %d ###\\n%s\\n\\n\", self->count, self->query);

self->a=0;
self->query=0;

}

pid$3::*mysql_parse*:return
/ self->a /
{
self->a=0;
self->query=0;
}

syscall::*write*:entry
/ self->a /
{
self->count++;
}

tick-$1
{
exit(0);
} 

Wednesday, February 10, 2010

drop schema on oracle

DROP USER
ALTER USER p$prodschema ACCOUNT LOCK;
 
BEGIN
    FOR x
        IN (SELECT 'alter system disconnect session ''' || sid || ',' || serial# || ''' immediate;'
                       sqlstr
            FROM v$session
            WHERE username = 'P$PRODSCHEMA')
    LOOP
        EXECUTE IMMEDIATE x.sqlstr;
    END LOOP;
END;
 
DROP USER p$prodschema CASCADE;

Monday, February 1, 2010

mongodb backup with zfs

http://www.mongodb.org/display/DOCS/fsync+Command

use admin
switched to db admin
> db.runCommand({fsync:1,lock:1})
{
 \"info\" : \"now locked against writes\",
 \"ok\" : 1
}
> db.currentOp()
{
 \"inprog\" : [
 ],
 \"fsyncLock\" : 1
}

> // do some work here: for example, snapshot datafiles...
/sbin/zfs/snapshot /mongo/mongo1@backup

> db.$cmd.sys.unlock.findOne();
{ \"ok\" : 1, \"info\" : \"unlock requested\" }
> // unlock is now requested.  it may take a moment to take effect.
> db.currentOp()
{ \"inprog\" : [ ] }


[Database]
server: localhost
user: root
password: pass
port: 27017

[ZFS]
zfs_command: /usr/sbin/zfs

; ZFS filesystem containing the MongoDB database files.
db_fs_name: mongo
db_fs_dir: /mong


import ConfigParser
import sys,os,time,commands,re

from optparse import OptionParser
from os.path import exists

from pymongo.connection import Connection
from pymongo.son import SON


txt_program_revision = \"0.1\"
txt_program_name = \"MoBack\"

args_parser = OptionParser(usage=\"%prog --filename MoBack.cfg -d directory\", version=txt_program_name + \" \" + txt_program_revision)
args_parser.add_option(\"-f\", \"--filename\", dest=\"FN_CONFIG\",help=\"Configuration file containing MONGODB and ZFS settings to use for backup run.\")
args_parser.add_option(\"-d\", \"--directory\", dest=\"DIRECTORY\",help=\"Copy backup to directory\")
args_parser.add_option(\"-N\", \"--no-destroy\", dest=\"NODESTROY\",action=\"store_true\", help=\"Ceated snapshot will be not destroyed.\",default=False )

arg_program_options, arg_leftover = args_parser.parse_args()

if arg_program_options.FN_CONFIG==None:
    print \"\\nMust supply a configuration filename. Please use --help for syntax.\"
    sys.exit(-1)

if arg_program_options.DIRECTORY==None:
    print \"\\nMust supply a directory where snapshot will send. Please use --help for syntax.\"
    sys.exit(-1)

### Load in configuration settings
config_parser = ConfigParser.SafeConfigParser()
try:
    f_config = open(arg_program_options.FN_CONFIG)
except IOError, e:
    print \"\\nCannot find \" + arg_program_options.FN_CONFIG + \". Please check the argument and try again.\"
    sys.exit(-2)

backup_dir = None
if not exists( arg_program_options.DIRECTORY):
    print \"\\nDirectory \" + arg_program_options.FN_CONFIG + \" don\'t exist. Please check the argument and try again.\"
    sys.exit(-2)
else:
    backup_dir = arg_program_options.DIRECTORY


config_parser.readfp(f_config)

# Validate individual required options
try:
    database_server= config_parser.get(\"Database\",\"server\")
    database_user  = config_parser.get(\"Database\",\"user\")
    database_pass  = config_parser.get(\"Database\",\"password\")
    database_port  = config_parser.get(\"Database\",\"port\")

    fn_zfs_cmd = config_parser.get(\"ZFS\",\"zfs_command\")
    fn_zfs_db_fs = config_parser.get(\"ZFS\",\"db_fs_name\")
    fn_zfs_db_fs_dir  = config_parser.get(\"ZFS\",\"db_fs_dir\")
except ConfigParser.NoOptionError, e:
    print \"\\n\" + repr(e)
    print \"Please make sure all required sections and options are supplied and try again.\"
    f_config.close()
    sys.exit(-3)

zfs_list_status, zfs_list_output  = commands.getstatusoutput(fn_zfs_cmd + \" list\")
if not re.compile(fn_zfs_db_fs).search(zfs_list_output, 1):
    print \"\\nNo ZFS DB filesystem named \" + fn_zfs_db_fs + \" exists. Please check your configuration and try again.\"
    sys.exit(-4) 
print \"\\nAll specified ZFS filesystems are present.\"


print \"\\n\\nMoBack is connecting to MongoDB:\"

try:
    connection = Connection( database_server , int(database_port))
    db = connection[\'admin\']
    db.authenticate(database_user, database_pass)
except:
    print \"Unable to connect to MySQL server \" + database_server + \". Please check the configuration file and try again.\"
    sys.exit(-5)

print \"\\tConnected to \" + database_server + \".\"

time_snapshot = \'auto-\'+ time.strftime(\"%Y-%m-%d_%H%M%S\")

print \"\\tPrepared MongoDB to ensure  consistency.\"
loc_cmd = SON()
loc_cmd[\'fsync\'] = 1
loc_cmd[\'lock\'] = 1
res = db.command(loc_cmd)

### Pull ZFS snapshots.
try:
    # Snapshot DB
    snap_name = fn_zfs_db_fs + \"@\" + time_snapshot
    print \"\\tSnapping ZFS DB filesystem.\"
    zfs_dbsnap_status, zfs_dbsnap_output = commands.getstatusoutput(fn_zfs_cmd + \" snapshot \" + snap_name)
    if zfs_dbsnap_status != 0:
        print \"An error occurred while executing the ZFS snapshot on \" + _fn_zfs_db_fs + \". Unlocking collections and quitting.\"
        coll = db[\'$cmd.sys.unlock\']
        coll.findOne()
        sys.exit(-7)
except:
    coll = db[\'$cmd.sys.unlock\']
    coll.findOne()
    print \"\\tAn unrecoverable error occurred while trying to pull the snapshots. We have unlocked the collections. Please check your system logs for details as to the ZFS error.\"
    sys.exit(-7)

print \"\\tUnlocking collections.\"
coll = db[\'$cmd.sys.unlock\']
coll.findOne()
print \"\\tcollections unlocked.\"
print \"MoBack snapshot run completed.\"

print \"\\n\\nSnapshots created:\"
print \"\\t\" + fn_zfs_db_fs + \"@\" + time_snapshot
sys.exit( 0)


if backup_dir:
    zfs_backsend_status, zfs_backsend_output = \\
        commands.getstatusoutput(fn_zfs_cmd + \" send \" + snap_name + \" > \"  + backup_dir +\"/\"+  _database_server+\"_\"+database_port+\"_\"+time_snapshot)

if zfs_backsend_status != 0:
    print \"\\nAn error occurred while executing the ZFS send on \" + fn_zfs_db_fs + \".\"
    print zfs_backsend_output
    sys.exit(-7)


if arg_program_options.NODESTROY != True:
    snap_re = re.compile(r\'@auto\\-\')
    if not snap_re.search(snap_name):
        print \"\\n\\nBad snapshot name.\"
        sys.exit(-1)

    print \"\\n\\nScript is going to destroiy snapshot \"+ snap_name +\".\"
    zfs_dbsdestroy_status, zfs_dbsdestroy_output = commands.getstatusoutput(fn_zfs_cmd + \" destroy \" + snap_name)
    if zfs_dbsdestroy_status != 0:
        print \"\\nAn error occurred while executing the ZFS destroy on \" +  snap_name + \".\"
        print zfs_dbsdestroy_output
        sys.exit(-7)
    print \"\\n\"+ snap_name +\" destroyed.\" 

ZFS has many problems with fragmentation.

Wednesday, January 20, 2010

MongoDB huge collections

I have to load 1 000 000 000 records to mongodb. It's not good idea to create indexes before this operation.
After first 40 000 000 speed decreesed from 10k/s to 1k/s.

Sunday, December 20, 2009

TDD Test Driven Development

Firmy szaleją na punkcie AGILE. W mojej firmie na przykład wprowadzono SCRUMa. Jestem DBA i widzę skutki działania programistów i czas jaki poświęcają na daną funkcjonalność oraz UTRZYMANIE.

  1. Fundamenty projektu. Początkowy etap rozwoju jest "najprostszy". Wszyscy są podekscytowani, programista ma coś nowego i 80% projektu powstaje bardzo szybko.
  2. Dopieszczanie projektu. Mamy fundamenty, wstawione okna i podłączony prąd (nie ma zamontowanych włączników tylko gołe druty), w łazience czeka najlepsze jacuzzi na świecie. Wykończeniowcy mozolnie dopieszczają nowy dom.
  3. Wejście mieszkańców. Horror, w jednym miejscu ktoś zapomniał wstawić włącznika i lokator dotknął dłonią przewodów pod napięciem, część włączników w ogóle nie działa. Okazało się, że rury są nieszczelne i woda wycieka ze ściany a nie leci do jacuzzi. Jesienią i zimą podwórze zamienia się w bagno bo studzienki nie są w stanie odprowadzić wody.
  4. Poprawki. Zrobiliśmy brakujący włącznik skuliśmy ściany i wymieniliśmy nie działającą część instalacji elektrycznej , poszerzyliśmy studzienki kanalizacyjne, nawet uszczelniliśmy rury. Okazało się jednak, że po uszczelnieniu rurociągu trzeba zmienić rury kanalizacyjne bo nie dają rady z odprowadzaniem zużytej wody. Podczas kucia uszkodziliśmy kable ethernetowe i przestał działać internet oraz system alarmowy oraz działająca do tej pory część instalacji elektrycznej. Zleceniodawca zerwał umowę i musimy płacić karę umowną.

Tak dokładnie wyglądają projekty informatyczne w dziewięćdziesięciu procentach wypadków. Na ratunek przyszły zwinne metody prowadzenia projektów. Niestety to nie jest panaceum na problemy. Scrum wymaga dobrych i doświadczonych programistów w projekcie. Programistów umiejących pisać testy.

Bez pisania testów nie da się wykorzystywać Scruma. Na dobrą sprawę młyn bez testów spowalnia tworzenie oprogramowania ponieważ iteracje często wymagają gwałtownych przeróbek i ręczne wyszukiwanie implikacji zmian ( nowych błędów ) to mordęga.

Dobry programista projektuje przed startem implementacji. Implementacje zaczyna od pisania testów. Nie da się przewidzieć wszystkich przypadków ale unika się kompromitujących wpadek.

Scrum jest prosty ale dla doświadczonych programistów.

http://en.wikipedia.org/wiki/Test-driven_development

Friday, December 4, 2009

Django Pisa (polskie czcionki)

I use Pisa to generate reports. I had problem with polish lettersm solution is to replace included fonts (arial, helvetica) with own.
Copy fonts to /project/directory/site_media/font.

#-*- coding: utf-8 -*- 
import cStringIO as StringIO

import ho.pisa as pisa

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.template import Context
from django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _

from arap.report.models import Review
from arap.report.models import Type
from arap.settings import  MEDIA_ROOT

@login_required
def print_report(request, id):
    """
    Generuje raport z przeglądu.
    """
    template = get_template('report/print.html')
    review = get_object_or_404(Review, id=id)
    context = Context({'pagesize':'A4', 'review':review, 'MEDIA_ROOT':MEDIA_ROOT})
    html  = template.render(context)
    result = StringIO.StringIO()
    pdf = pisa.pisaDocument(StringIO.StringIO(html.encode('UTF-8')), result)
    if not pdf.err:
        response = HttpResponse( result.getvalue() )
        
        response['Content-Type'] = 'application/pdf'
        response['Content-Disposition'] = 'attachment; filename="%s-%s-%s.pdf";' \
            %(review.server,review.report_type, review.created)
        return response
    return HttpResponse(u"Coś nie bangla.", mimetype='text/html')

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<style type="text/css"> 
@font-face {
   font-family: "arial","helvetica","symbol";
   src: url({{ MEDIA_ROOT}}/font/arial.ttf);
}

@font-face {
   font-family: "arial black";
   src: url({{ MEDIA_ROOT}}/font/arialbd.ttf);
}

@font-face {
   font-family: "verdana";
   src: url({{ MEDIA_ROOT}}/font/verdana.ttf);
} 


@font-face {
   font-family: "Times New Roman" ,"wingdings";
   src: url({{ MEDIA_ROOT}}/font/Times_New_Roman.ttf);
}

@font-face {
   font-family: "Comic Sans Ms";
   src: url({{ MEDIA_ROOT}}/font/Comic_Sans_MS.ttf);
}

@page {
  margin: 1cm;
  margin-bottom: 2.5cm;
  @frame footer {
    -pdf-frame-content: footerContent;
    bottom: 2cm;
    margin-left: 1cm;
    margin-right: 1cm;
    height: 1cm;
  }
} 

html, body, table, caption, tbody, tfoot, thead, tr, th, td {
    font-family: "Times New Roman";
}
</style>

<title>Raport {{ review.report_type }} {{ review.server }} {{ review.created }}</title>
</head>
<body> 
  {{ review.report|safe }} 
  <div id="footerContent">
    {%block pager %}
      <pdf:pagenumber>
    {%endblock%}
  </div>
</body>
</html>

Saturday, November 7, 2009

How to find locks in postgres ?

Table pg_locks is very usefull...


select
 pg_stat_activity.datname,
 pg_class.relname,
 pg_locks.transaction,
 pg_locks.mode,
 pg_locks.granted,
 pg_stat_activity.usename,
 substr(pg_stat_activity.current_query,1,30),
 pg_stat_activity.query_start,
 age(now(),pg_stat_activity.query_start) as "age",
 pg_stat_activity.procpid
from 
 pg_stat_activity,
 pg_locks left outer join pg_class on (pg_locks.relation = pg_class.oid)  
 where
 pg_locks.pid=pg_stat_activity.procpid order by query_start;