postgresql etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
postgresql etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

3 Temmuz 2012 Salı

PostgreSQL ile Random Kod Üretimi


Geçen günlerde lazım oldu, bir durum için 15 milyon adet random 11 karakterli bir text oluşturmam gerekti. Ufak bir script(bash yada c ile) üretmekte bir seçecekti fakat bir script ile 15 milyon unique satır oluşturmanın bazı zorlukları var. Kısaca bunları sıralayayım ki bir daha aynı şeyleri düşünmek zorunda kalmayalım.

  1. Tekilliğin (unique) sağlanması için her bir kod üretildikten sonra ya bir array,map, dict gibi birşeyde tutulup kontrol edilecek
  2. ikinci bir seçenek her ürettiğimiz kodu gidip veritabanına bu var mı? diye soracak bir select sorgusu olacak. (her seferinde db'ye açılacak bağlantılardan bahsetmiyorum bile)
  3. unique olmasını sağladığına emin olduğumuz bir algoritma yazılacak.
açıkcası bunlardan bana en matıklı geleni doğru dürüst bir algoritma yazmak, lakin bunun üretileceği tabloda daha önce herhangi bir kurala uygun olmadan üretilmiş 100 milyon kod daha olduğunu düşünürsek, yazacağımız algoritma biraz kasacaktı - ki bu işin 3 saat içinde bitmesi gerekiyordu.

Bu yukarda yazdığım sebeplerden mütevellit aşağıda bu işi direk olarak db üzerinde halleden basit bir pl/pgsql scripti var. biraz açıklamaya çalışarak paylaşayım istedim.


Öncelikle test tablomuzu yaratalım.

CREATE TABLE random_code (code varchar(11));

ilk fonksiyonumuz random bir text üreten fonksiyon.
Aldığı parametreler;

  • prefix : her kodun başına ekleyeceğimiz bir işaret ('TEST','XXX' gibi)
  • code_length : üretilecek kodun uzunluğu (prefix dahil)
farkettiğiniz üzere karakter listesinde 0 ve sesli harfler yok bunun sebebi, 0 rakamı 'o' harfi ile karıştırılabiliyor, sesli harfler ise random olarak bir araya geldiklerinde 'GÖT','MEME' gibi çokta 
insanlara vermek istemeyeceğiniz kodlar üretebiliyor. Bu yüzden onlarıda çıkardım. bu metodun kalan kısmı angarya.


CREATE OR REPLACE FUNCTION create_code(prefix varchar,code_length integer)
RETURNS text AS
$$
DECLARE
  chars text[] := '{1,2,3,4,5,6,7,8,9,B,C,D,F,G,H,J,K,L,M,N,P,Q,R,S,T,V,W,X,Y,Z}';
  result text := '';
  i integer := 0;
BEGIN
IF code_length < 1 then
    RAISE EXCEPTION 'Kod uzunlugu 1 den buyuk olmalıdır';
  END IF;

  result := result || prefix;

  FOR i IN 1.. code_length - code_length(prefix) LOOP
    result := result || chars[1+random()*(array_length(chars, 1)-1)];
  END LOOP;
  RETURN result;
END;
$$ language plpgsql;



Bütün olayın döndüğü yer aslında burası. Aldığı parametreleri açıklayayım;

  • count : üretilecek kupon adeti
  • prefix : her kodun başına ekleyeceğimiz bir işaret ('TEST','XXX' gibi)
  • code_length : üretilecek kodun uzunluğu (prefix dahil)
şimdi burada declare'in altında 2 tane değişken tanımlamışız, code_l ve temp_rec. code_l üretilen ve yazılacak olan kodun son hali, temp_rec üretilen kodun daha önce var olup olmadığını tutan 0 ya da 1 olabilen bir değişken.

gelelim olaya, ilk olarak temp bir tablo yaratıyorum. CREATE TEMP TABLE bu tabloda bir session içinde yaratılacak tüm kodları geçici olarak yazacağım. Bunun amacı, üretilen her bir kodun daha önceden üretilip üretilmediğini 100 milyon satır içeren bir tablodansa daha küçük bir tabloda aramak. Arkasından gelen CREATE INDEX ifadesini tahmin edersiniz sanrım. Burada kafanıza eğer 'Acaba bu index temp tablo gidince düşecek mi ?' sorusu geliyorsa, rahat olun düşecek o da.


Devam edersek, her bir kod'u WHILE döngüsü yazarak, eğer kod daha önceden yazılmışsa yazılmamışı bulana kadar yeniden üretmek için yapıyorum. daha sonrasında her üretilen kodu kesinlikle temp tabloya ve arkasından master tablomuza yazıyorum.

CREATE OR REPLACE FUNCTION generate_randomcode
(
count integer,
prefix text,
code_length integer
)
RETURNS void AS
$$
DECLARE
code_l text;
temp_rec int;
BEGIN

CREATE TEMP TABLE codes_tmp(a text) WITHOUT oids ON commit DROP;
CREATE INDEX temp_code_idx ON codes_tmp(a);
    FOR c IN 1..count LOOP
        code_l = create_code(prefix,code_length);
        SELECT count(*) INTO temp_rec FROM codes_tmp WHERE a = code_l;

        WHILE temp_rec != 0 LOOP
                code_l = create_code(prefix,code_length);
                SELECT COUNT(*) INTO temp_rec FROM codes_tmp WHERE a = code_l;
        END LOOP;
        INSERT INTO codes_tmp VALUES (code_l);
        INSERT INTO random_code (code) VALUES (code_l);
        END LOOP;
END;
$$ LANGUAGE 'plpgsql';

Tüm bu olan biteni anladıktan sonra,
SELECT generate_randomcode(10,'TEST',8);
dediğimizde, 8 karakterli TEST ile başlayan toplamda 10 adet kodumuz olmuş olacak.

15 Mart 2012 Perşembe

postgresql 9.0 to 9.1 upgrade

Today, when i try to upgrade postgreSQL in our production servers i got some difficulties so i briefly explain the all scenario here.

first of all stop postgresql  
sudo /etc/postgresql9-0 stop

get latest RPM's from postgresSQL repos
i use wget to take rpm then

rpm -ivh your_postgresql_rpm.rpm
yum install postgresql91.x86_64 postgresql91-contrib.x86_64  postgresql91-devel.x86_64 postgresql91-libs.x86_64 postgresql91-server.x86_64

after installation complete initialize new cluster (do not start just initdb)
sudo /etc/init.d/postgresql9.1 initdb

ok now, there is a problem in ldconfig's lets change them (details here

cd /etc/ld.so.conf.d
mv postgresql-9.0-libs.conf postgresql-9.old-libs.conf
ldconfig

now lets start to play with pg_upgrade
pg_upgrade has great syntax

/usr/pgsql-9.1/bin/pg_upgrade -d /var/lib/pgsql/9.0/data/ -D /var/lib/pgsql/9.1/data/ -b /usr/pgsql-9.0/bin/ -B /usr/pgsql-9.1/bin/ -v

-d old data dir
-D new data dir
-b old binary dir
-B new binary dir

and after installation complete. it's done :)

22 Aralık 2011 Perşembe

Postgresql SSL Kurulumu

postgresql bağlantı ayarları kısmında SSL özelliğinin var olduğunu göreceksiniz. Şimdi burda bu SSL'i neden ve nasıl kullanacağımızı bilmek mühim. Ben burda basit olarak  sorgularınızın network üzerinde (client dan postgresql server'ınıza) şifreleyerek nasıl göndereceğinizden bahsedeceğim.

ilk olarak SSL kullanmadığımız bir bağlantıyı izleyip neler olup bittiğini görelim. ben network'u izlemek için tcpdump kullanacağım siz istediğiniz bir yazılımla ortamı dinleyebilirsiniz.

tcpdump -i eth0 -X -s 3000 host 10.22.22.76
malumunuz burdaki 10.22.22.76 no'lu adres, gelen paketleri izleyeceğimiz veritabanı server makinasının adresi.

daha sonra neler olup bittiğini görmek için aynı makinaya psql ile local makinamdan bağlanıp, çeşitli sorgular yollayacağım. bu arada gözünüz bir yandan da tcpdump çıktısında olsun.

psql -U postgres -d test -h 10.22.22.76
-- test için bir tablo yaratalım 
create table foo (id integer,password varchar(32));
-- şimdi bir satır girelim ve tcpdump ile bu girdiğimiz veriyi izleyelim
insert into foo values (1,'en gizlisinden password');

eğer girdiğimiz datayı tcpdump ile takip ettiysek şöyle bir çıktı görmeniz gerekiyor.


farkettiyseniz orada bir yerlerde bizim gönderdiğimiz sorgu ve dönüşünde postgres'in bize verdiği
yanıtı görebilirsiniz. Bunu biraz düşünün neler olabilir. Eğer tehlikeli olabileceğini düşünüyorsanız okumaya devam.

peki gelelim SSL kurulumuna.

ilk olarak bir SSL sertifikası yaratmamız gerekiyor. sırasıyla aşağıdakileri uygularsak eğer tamamdır,

#openSSL paketlerinin kurulu olduğunu varsayıyorum tabi ki.
openssl genrsa -des3 -out server.key 1024
#CRT dosyasını çıkaralım
openssl rsa -in server.key -out server.key
openssl req -new -key server.key -x509 -out server.crt
# istediğiniz encryption algoritmasını kullanabilirsiniz. (man openssl) 

bunları yaptıktan sonra yarattığımız bu iki dosyayı (server.key,server.crt)
$PGDATA klasörünün altına taşımamız gerekiyor.

Daha sonra $PGDATA/postgresql.conf içinde SSL = off kısmını on olarak değiştirip
server a restart attığımızda aynı sorguları tekrar denersek

burda mutlaka ama mutlaka atlamamız gereken bir kısım var, yarattığımız dosyaların
sahibi (owner) mutlaka postgres olmalı ve izinler 0600 olaral verilmeli.
chown postgres server.*
chmod 0600 server.*

psql -U postgres -d test -h 10.22.22.76
-- şimdi bir satır girelim ve tcpdump ile bu girdiğimiz veriyi izleyelim
insert into foo values (1,'en gizlisinden password');

tcpdump çıktısında şöyle şeyler göreceğiz.


gördüğümüz gibi artık bağlantılarımızda dışardan birisi dinlediğinde anlamsız veriler görecektir. tabi bu çok basit bir çözüm ( en ufak yapılması gereken diyelim) bunun dışında her bir client ile de sertifika paylaşımı sağlamak gibi daha iyi çözümler var. bunlarıda daha sonra anlatacağım.

19 Eylül 2011 Pazartesi

PostgreSQL 9.0 Ubuntu kurulum

geçenlerde gene biri sormuştu apt ile nasıl yapacaz edecez diye.


sudo add-apt-repository ppa:pitti/postgresql


repo yu ekledikten sonra bir update çakalım

sudo apt-get update


akabinde yüklememizi yapalım

sudo apt-get install postgresql-9.0


bitti.

19 Ağustos 2011 Cuma

PostgreSQL Replikasyon Çeşitleri

Shared Disk Failover

Aynı disk kümesi üstünde birden fazla veritabanı çalıştırarak failover anında diğer diskin 0 data kaybıyla devreye girmesini sağlıyor. Network üzerinden de bunu devreye almak mümkün fakat dikkat edilmesi gereken şey sistem ful POSIX desteğinin olması gerekiyor. Network üzerinden kurduğumuz sistemin dezavantajı, eğer disk giderse yedekte olan diski devreye alamayız. Bir diğer ise master çalışırken, slave paylaşılan klasöre erişmemeli.

File System (Block-Device) Replication

Shared diske benzer lakin burada mantık disklerin aynen bir kopyasını üretmektir. Dikkat edilmesi gereken şey bu disklerin aynı verileri aynı yere ve aynı sırayla yazması olacaktır. Linux da bunu DRBD dosya sistemi ile yapabiliriz.

Warm and Hot-Standby Using Point in Time Recovery(PITR)

Stream den write ahead log (WAL) okunmasıyla yapılıyor. Master düştüğünde slave neredeyse veri kayıpsız devreye girip master yerine geçebiliyor. Asenkroniktir. (PostgreSQL 9.0)

Trigger based Master-Standby Replication

Bathc olarak slave e yollar verileri. Slony-I çalışan örneği.

Statement-Based Replication Middleware

Araya bir katman atarak gönderilen sorguların bütün replikalarda çalışmasını sağlıyor. Pgpool-II ve Sequoia çalışan örnekleri.

Asynchronous Multimaster Replication

Her makina ayrı ayrı çalışır belli periyodlarla verileri birleştirir ve transaction conflictlerini çözer. Bucardo çalışan örneği

Synchronous Multimaster Replication

Her makina ayrı çalışır aynı anda bütün makianlara insert query'leri yollanır. Çok yazma işlemi olan sistemlerde lock lara sebep olabilir. PostgreSQL desteklemez lakin prepare transaction ve commit prepared ile yazılım ile halledilebilir.







Not: 9.1 den sonra daha güzel seçeneklerimizde olacak.

11 Temmuz 2011 Pazartesi

could not create IPv6 socket: Address family not supported by protocol

if you get this error and sure that it is not from kernel or other stuff.
You should check pg_hba.conf file
if you wrote wrong entry on that file, i get the same error. May be this will help you.

ex:
wrong entry:

host    all             replication     192.168.3.140        trust #did you notice i forget to give mask /32. when i put and restart postgresql, it start without error.

5 Haziran 2011 Pazar

FATAL: could not create shared memory segment: Invalid argument

2011-06-05 16:08:26 EEST FATAL:  could not create shared memory segment: Invalid argument
2011-06-05 16:08:26 EEST DETAIL:  Failed system call was shmget(key=5433001, size=278364160, 03600).
2011-06-05 16:08:26 EEST HINT:  This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter.  You can $
        If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter, in which case raising the request size or reconf$
        The PostgreSQL documentation contains more information about shared memory configuration.

just change the value on postgresql.conf -> shared_buffers to smaller value then kernel SHMMUX value.