Mysql Replikasyon Yapılandırması
Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYpcuO5H' (Errcode: 28 - No space left on device) in /usr/share/nginx/html/syslogs/wp-includes/class-wpdb.php on line 2349
Sql Replication uygulaması kısaca bir veri tabanının bir kopyasını başka bir sunucu üzerine sürekli güncel bir şekilde tutmaya yarayan ve oldukça fazla kullanım alanı olan güzel bir uygulamadır.
Örneğin çok fazla işlem hacmine sahip bir veritabanı uygulamasında sql sunucusunun kaynakları büyük miktarlardaki veri giriş çıkış işlemlerine yetişmekte zorlanabilir bu da sunucunun yerlerde sürünmesine neden olabilir. Bu performans sorunlarını, sunucunun donanımsal kaynaklarını arttırarak çözmek bazı durumlar için mümkün olmayabilir. İşte bu tip durumlarda veritabanınızın bir kopyasını ikinci bir sunucu üzerinde çalıştırmak isteyebilirsiniz. |
Ya da aynı şekilde verinizin güvenliğini sağlamak amacıyla da kopya bir database'e ihtiyaç duyabilirsiniz. Hatta aynı veritabanının birden fazla fiziksel lokasyonda bulunuyor olması da gerekebilir.
İşte bu gibi senaryolar için veritabanınızı bir başka sunucuya replike edebilir ve devamlı güncellenen bir kopyasını ilgili serverda bulundurabilirsiniz. Makalenin devamında mysql üzerinde master to slave replikasyon işleminin nasıl yapıldığına ait notları bulabilirsiniz.
Ben mysql sunucularını genelde freebsd üzerinde çalıştırmaktayım, Bu nedenle mysql replication ile ilgili yapılandırma işlemleri freebsd üzerinde yapılmıştır. Ancak siz farklı bir OS kullanıyor olasınız da işleyiş temel olarak aynı olduğundan dolayı, işletim sisteminize uygun küçük değişiklikler yaparak bu yazıda anlatılanlardan yararlanabilirsiniz.
Yapılandırma ile ilgili bölüme geçmeden önce mysql replication uygulamasının teoride nasıl çalıştığıyla ilgilli kısa bir bilgi vermek istiyorum.
Mysql'de replication işleminin temel olarak master to master ve master to slave diye tabir edilen iki şekli vardır. Kısaca değinmek gerekirse;
Master to Master Replication
Master to Master mimarisinde iki adet master sunucu bulunur ve veritabanlarından herhangi birinde, insert, update, delete vs. gibi bir işlem gerçekleştiğinde, bu işlem diğer veritabanına da yansıtılır. Bu şekilde veri giriş/çıkışının hangi veritabanında olduğunun bir önemi yoktur. Her şekilde iki veritabanı birbirine replike ediliyor olur ve güncel kalmaları sağlanır.
Bu yöntem master to slave'e oranla daha komplike olduğundan dolayı teknik anlamda, örneğin veritabanınızın karmaşık bir yapıya sahip olması nedeni ile işletim sorunlarını da beraberinde getirebilir.
Master to Slave Replication
Bu makalede nasıl yapılacağı anlatılacak olan bu replikasyon şekli ise, master olarak belirlenen sunucuda gerçekleşen işlemlerin slave olarak belirlenen sunucuya yansıtılmasından ibarettir. Bu mimari de yapılan insert, update, delete vs. gibi tüm işlemler master sunucuda yapılır ve slave'e yansıtılır. Sonuç olarak replikasyon işlemi tek yönlü olarak yapılmaktadır.
Konuya teorik olarak değindikten sonra master to slave replication işleminin nasıl yapıldığına geçebiliriz.
Öncelikle iki farklı bilgisayarda çalışan birer mysql sunucunuz olduğunu varsayıyorum.
İşe master sunucusunda ki ayarlardan başlayacağız.
Master Sunucunun Yapılandırılması
İlk olarak mysql ayarlarının belirtildiği my.cnf dosyasında mysql'in networking özelliğinin açık olup olmadığından ve sunucu üzerinde tanımlı tüm ip'lere bind edilip edilmediğinden emin olmamız gerekiyor.
my.cnf dosyasını editleyin (freebsd'lerde /var/db/mysql dizini altında bulunur.) ve eğer varsa aşağıdaki satırların comment out (#) edilmiş olduğuna emin olun.
#skip-networking #bind-address = 127.0.0.1
Yukarıdaki ilk satır networking desteğini etkisizleştiriyor ikincisi ise sadece mysql'in loop back üzerinden bind edilmesini söylüyor. Bu satırların başında # yok ise bu durumda mysql network üzerinden bağlantı kabul etmeyecektir.
Şimdi de gene my.cnf dosyasında [mysqld] segmesinde aşağıdaki satırların var olduğundan ve comment out (#) “edilmemiş” oluduğundan emin olun. (İlgili satırlar ön tanımlı olarak mevcut olmalıdır; eğer yoksa aşağıdaki gibi ekleyebilirsiniz.)
log-bin=mysql-bin server-id=1
Bu satırların açıklamaları da şöyle; birinci satır mysql'in binary logging özelliğinin etkinleştirilmesini söylemektedir. Replication işlemleri için binary logları kullanılmaktadır. Master'da yapılan her işlem binary olarak loglanır ve slave sunucu masterda yapılan değişiklikleri anlayabilmek için bu binary logları kullanır. İkinci satır ise ilgili sunucunun Master olduğunu belirtmek için kullanılan ID numarasıdır.
Son olarak, my.cnf dosyasına (örneğin log-bin=mysql-bin satırının hemen altına) replike etmek istediğimiz database'le ilgili bilgiyi girelim;
binlog-do-db=testdb
Görüldüğü gibi testdb isimli bir veritabanım var ve bu veritabanını replike edilmesi üzere belirtiyorum.
Şimdi de değişikliklerin devreye girmesi için mysql servisini restart edelim.
# /usr/local/etc/rc.d/mysql-server restart
Master sunucunda my.cnf için yapılması gerekenler bunlardı.
Şimdi root yetkisi ile mysql sunucusuna bağlanıp, replikasyon yetkisine sahip bir kullanıcı oluşturacağız:
# mysql -u root -p Enter password:
Root şifreinizi girip login olduysanız sırası ile aşağıdaki komutları verip -kırmızı alanları kendinize göre düzenlemeyi unutmayın- kullanıcıyı oluşturabilirsiniz;
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'sifreniz'; mysql> FLUSH PRIVILEGES;
Şimdi, replike edilecek database'in durum bilgisini almak için sırası ile aşağıdaki komutları verin.
mysql> USE testdb; mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS;
Show master status dediğiniz zaman replike edeceğiniz db'nin durumunu gösteren, aşağıdakine benzer bir çıktı almanız gerekir;
+------------------+----------+---------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+---------------+------------------+ | mysql-bin.000002 | 351 | testdb,testdb | | +------------------+----------+---------------+------------------+ 1 row in set (0.00 sec)
Görüldüğü gibi mysql-bin.000002 isimli binary log kullanılıyor ve pozisyonu 351.
Bu bilgileri bir yere kaydedin; zira slave tarafında yapılacak olan ayarlamalar sırasında bu bilgiler lazım olacak.
Şimdi quit diyip çıkalım.
mysql> quit;
Master tarafında yapılması gereken işlemler hemen hemen bitti. Bundan sonraki adım, master sunucudaki testdb isimli veritabanının son halini slave olarak belirlediğiniz mysql sunucusuna aktarmaktan ibaret.
Bu işlemi yapmanın bir iki yolu var; bunlardan birisi (ve bence en kullanışlısı olanı) mysqldump ile slave üzerinden master'a bağlanıp, testdb isimli veritabanının bir yedeğini almak ve alınan bu dump dosyasını slave sunucu üzerine restore etmek.
Mysqldump dışında, masterdaki database'i slave üzerinde çalıştırmak için kullanılabilecek diğer yöntemlere örnek olarak, bir sql management programı olan SQLyog isimli bir yazılımı kullanmak ve export/import özelliğinden yararlanarak datayı bir yerden bir yere taşımayı verebiliriz. Bunun dışında slave üzerinde LOAD DATA FROM MASTER; komutunu kullanabilir ve verinin masterdan yüklenmesini sağlayabilirsiniz. Ancak bu komut bir süre sonra mysql'den kaldırılacağı için kullanmanızı tavsiye etmem.
Neyse, bu yöntemler arasında en kullanışlı olanı bana göre mysqldump demiştim ve e bu nedenle bu yöntemin nasıl uygulanacağını anlatacağım.
Master'dan Slave'e Manuel Restore
Bu işi yapabilmek için master mysql sunucunuzda slave sunucunun bağlanabileceği ve backup alabilmesi için select komutu çalıştırma yetkisi bulunan bir kullanıcıya ihtiyacınız var. Yukarıda slave'in master'a bağlanması için bir kullanıcı açmıştık;
Bu işi yapabilmek için master sunucusunda slave üzerinden bağlantı kabul eden ve select yetkisi tanıyan bir kullanıcı bulunması gerekiyor. Önce bu kullanıcıyı açalım ve testdb'den select yapabilmesi için yetki verelim.
Master mysql sunucunuza bağlanın ve aşağıdaki komutları çalıştırın.
Not: Kırmızı bölümleri kendinize göre düzenlemeyi unutmayın.
mysql> CREATE USER 'kullanici_adi'@'slave_mysqlin_ipsi' IDENTIFIED BY 'sifre'; mysql> GRANT SELECT, LOCK TABLES ON testdb.* TO 'backupuser'@'slave_mysqlin_ipsi'
Yukarıdaki komutlar ile master sunucusu üzerinde replike edilecek testdb isimli veritabanına select ve lock tables yetkisi ile erişebilecek bir kullanıcı tanımlamış olduk.
Şimdi slave sunucuya geçip aşağıdaki komutu çalıştırarak ilgili db'nin yedeğini alabiliriz.
Not: Bu işlemi direk komut satırından çalıştırın.
# mysqldump -h master_sunucunun_ipsi -u kullanici_adi -psifre testdb > testdb.sql
Bu komutla da msater sunucusuna (açmış olduğumuz kullanıcı ile) bağlanıp testdb isimli veritabanının yedeğini aldık.
Şimdi bu yedeği slave mysql'e restore edeceğiz.
Önclikle, slave mysql'e bağlanın ve aşağıdaki komutlarla, masterda bulunan ve replike edilecek olan database'le aynı isimde boş bir database oluşturun ve mysql shell'den çıkın.
# mysql -u root -p
Enter password:
mysql> create database testdb;
mysql> quit;
Database oluşturulduğuna göre, almış olduğumuz dump dosyasını üzerine restore edebiliriz.
# mysql -u root -psifre testdbtestdb.sql
Not: -p'den sonra boşluk olmaması gerekiyor.
Herşey yolunda gitti ve herhangi bir hata almadıysanız database restore edilmiş olmalı.
Şimdi master tarafında son bir şey yapmamız gerekiyor. Hatırlarsanız masterdaki veritabanının log ve pozisyon bilgisini alma sırasında FLUSH TABLES WITH READ LOCK; komutunu kullanmıştık. Şimdi lock durumunu ortadan kaldırmak gerekiyor.
Bunun için master mysql sunucusuna shell'den bağlanalım ve unlock komutunu verelim.
# mysql -u root -p Enter password: mysql> UNLOCK TABLES; mysql> quit;
Master ile ilgili yapılacak işlemler bu kadardı. Sırada Slave ile ilgil yapılandırmalar var.
Slave Sunucunun Yapılandırılması
Şimdi slave sunucusuna, master sunucu ile ilgili bilgileri vereceğiz. Bu işlem için gene my.cnf dosyasından yararlanıyoruz.
my.cnf'yi açın ve aşağıdaki satırı [mysqld] segmesine ekleyin:
Not: server-id değeri master'da 1 idi, burada da 2 oluyor. Bu değer her sql için unique olmalı. Yani yeni bir slave eklerseniz id'si 3 (ya da üstü) olmalı.
server-id=2
Şimdi de mysql'i restart edeceğiz.
# /usr/local/etc/rc.d/mysql-server restart
Son olarak slave'nin replikasyona başlaması için masterdan alarak -bir kenera not ettiğimiz- log adı ve pozisyon bilgilerini vererek replikasyona balamasını sağlayacağız.
Slave sunucunuzun mysql shell'ine bağlanarak aşağıdaki gibi slave stop komutunu verin.
#mysql -u root -p Enter password: mysql > SLAVE STOP;
Şimdi de bahsettiğim bilgileri şu komut ile veriyoruz. (Kırmızı ile belirtilmiş bölümleri kendinize göre düzenlemeyi unutmayın.)
CHANGE MASTER TO MASTER_HOST='master_mysqlin_ipsi', MASTER_USER='slave_user', MASTER_PASSWORD='sifreniz', MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=351;
Görüldüğü gibi bold olarak belirtilmiş değerler master tarafındaki binary dosyasının ismi ve pozisyon numarasını teşkil ediyor. Bunun dışındakiler de master sunucunuzun ip adresi, masterdaki replikasyon kullanıcısının adı ve şifresinden ibaret.
Komutu girdiniz ve sorunla karşılaşmadıysanız, slave'i start edebilir ve replikasyona başlanmasını sağlayabiliriz.
mysql > SLAVE START; mysql > quit;
Hepsi bu kadardı.
Normal şartlarda replikasyon işinin başlamış ve master sunucuda yapılan işlemlerin slave'e yansıtılıyor olması gerekir. Bunu denemek için master'daki testdb veritabanına bir kayıt ekleyip hemen ardından aynı kayıdın slave mysql'deki testdb veritabanında bulunup bulunmadığını kontrol edebilirsiniz.
Kaynak:
http://dev.mysql.com/doc/refman/5.0/en/replication.html
http://www.howtoforge.com/mysql_database_replication
Bu yazılar da ilginizi çekebilir:
- MySQL Replication durumunu bir script ile check etmek
- MySQL Full-Text Search Minimum Length Limitini Değiştirmek
- Mysql Server İçin Root Şifresi Tanımlamak
- MySQL: InnoDB Database Ebatının Küçültülmesi – Shrink ibdata1
- Komut Satırından MySQL Kullanıcısı Oluşturmak
Okuma işleminin çok olduğu projelerde kullanılabilecek bir yapı. Faydalı bir makele olmuş. Ellerinize sağlık.
[Cevapla]
Hocam öncelikle ellerinize sağlık. Yalnız takıldığım bir nokta var ona değinmeden geçemiycem. Sql replikasyon database in performansını arttırmaz? Zira girilen her kaydın kopyası diğer db ye de yazılacağından blakis :) performans düşüşü olur. Tabi ki db nin birebir kopyasının tutulması müthiş bir olay. (Nacizane fikrimi yazdım, en azından ben böyle biliyorum. MSSQL de bu şekilde)
[Cevapla]
Selamlar,
Örnek olarak çok yüklü işlem hacmi olan bir siteniz ya da uygulamanız varsa replikasyon yapabilir, uygulamanıza yazma işleri için 1. okuma işlemlermi için 2. mysql’i kullan diyebilirsiniz. Bu şekilde ayrıma gitmeniz toplamdaki performansı arttıracaktır.
[Cevapla]
Bilgilendirme için teşekkürler.
[Cevapla]
Merhaba,
Yazı için teşekkürler. İşlemleri yaparken iki hata ile karşılaştım ve yorumlarınızı almak istedim.
– “mysqldump -h master_sunucunun_ipsi -u kullanici_adi -psifre testdb > testdb.sql”
testdb.sql dosyasına sadece parametre kısmı geliyor. Tablo yaratma komutlarını alamıyorum.
– “Start Slave” komutunda da “ERROR 1200 (HY000): The server is not configured as slave; fix in config file or with CHANGE MASTER TO” hatasını almaktayım.
Teşekkürler…..
[Cevapla]
Merhaba,
CEntos’ta çalıştıramadım belki gözümden birşey kaçtı ancak ubuntu’da çalıştırabildim…
Teşekkürler…
[Cevapla]
Evet, dediğiniz gibi gözünüzden bir şey kaçmış olabilir.
[Cevapla]
Nedense aynı şekilde bende de (ubuntu server) slave sunucu üzerinde my.cfg dosyasına slave bilgilerini girip yeniden başlatmak istediğim de başlamıyor…
[Cevapla]
Aldığınız hatayı söylerseniz yardımcı olmaya çalışırım.
[Cevapla]
Mysql’in kendi documentation’un bakarak,
/etc/my.cfg dosyası altında
master-host=master_mysqlin_ipsi
master-user=slave_user
master-password=sifreniz
master-connect-retry=60
replicate-do-db=testdb
bu parametre ayarının olmadığı gördüm. Bu parametreleri girince servis başlamıyordu. Bu parametleri kullanmadan bu bilgileri mysql komut sisteminden girince replike başladı
[Cevapla]
Selamlar,
Makale biraz eski ve bahsettiğiniz ayarlar yeni sürüm MySQL’lerde kaldırılmış durumda. Bilgilendirme için teşekkür edereim. Makaleyi ayrıca güncelleyeceğim.
[Cevapla]
Merhabalar,
öncelikle çok çok iyi bir makale, elinize sağlık.
Birden fazla lokasyondaki MASTER ları tek lokasyonda SLAVE olarak toplamak mümkün mü tabiki her biri ayrı database, ben SLAVE tarafında birden fazla MASTER ayarı yapamadım.
[Cevapla]
Merhaba
Yazıda “testdb” belirtilen db posizyon ve log numarasi , Slave girilenden yanlıs gozukuyor. :) (Cok onemli degil ama okuyanlar için kolaylık olur.) Benim 2 adet sorum olacak.
1. M-S yapısını gayet basarili olarak calisiyroyurm. Bir database daha ekledigimde ilgili database status ve posizyon numarasini almadan replica edebiledigini gordum. Sanırım pozisyon ve log numarasi bir kereye mahsus giriyoruz ?
2. M bir sorun oldugunda S olan veriye yazılabilri durumda oluyor. M ayağı kalktığın haliyle S , M db yeni eklenenleri kopyalamayacak. Bu durumda M-S yerine M-M yapmak daha mantıklı olur. Yada bu durumda elle S yeni eklenen db dump edip M restore etmek gibi manuel bir yontem mi izlemek gerekir. Siz bu durumda ne onerirsiniz ?
Teşekkürler.
[Cevapla]
İlginiz için teşekkür ederim. Hatalı yeri düzelttim.
Pozisyonun yerini vermemizin ana sebebi, iki sunucu arasında oluşabilecek olası fark nedeni ile düzgün senkronizasyon yapılabilmesinden ibaret. Bu anlamda bir kez girmeniz yeterli.
M-M yapmak bir yöntem (bunun için Percona Xtracluster’a bakmanızı öneririm.) M-S yapısında ise dediğiniz gibi Slave’e yazarsanız artık o Slave olmaktan çıkıyor ve teorik olarak master oluyor, bu nedenle eski master’i slave yapmanız ve senkronize etmeniz gerekiyor.
[Cevapla]
Merhaba,
Benim şöyle bir sorum var.
Master-Master yapı kuracağım fakat benim bazı isteklerim var bunu araştırdım ama pek sorumun cevabını bulamadım.
Örn:
alışveriş veritabanı var bunun içinde 3 tane tablo olsun.
Ürün tablosu
kategori tablosu
sipariş tablosu
bütün tablolar otomatikman replice olacak ama ben “ürün” tablosunda delete işlemi olduğunda diğer master veritabanın da bu işlem gerçekleşmesin. insert, update işlemleri olsun istiyorum.
Bunu nasıl yapabilirim ???
[Cevapla]