28 Ekim 2009 Çarşamba

mysql replication

Web ve daha önemlisi bütün otomasyon verilerinin üzerinde bulunduğu sunucunun her gece yedeğini alıyorum. Ancak gün içinde onca işlem yapılmışken akşam üstü bir sorun yaşanması oldukça kötü bir senaryo.
Bunun için gün içinde değişen dosyaları kaybetmek göze alınsa bile, mysql verileri için bu olası olamayacağından, mysql i yedek sunucu ile replike (paralel) olarak çalıştırmaya karar verdim.
Şu şekilde;

Öncelike benim kurduğum tek yönlü mysql replication işinin mantığı şu;
0-İki tane sunucum var; master (asıl sunucu (master), veriler burada değiştirilir, ve diğer sunucu (slave) burada verileri değiştirilmez, ama istenirse select işlemleri yapılabilir ). Slave sunucu master sunucunun mysql'ine ulaşabiliyor olmalı, firewall kontrol et.
1-Mater sunucuya, sen mastersin, artık dur yeni bir update işlemi yapma, ayrıca bundan sonra şu databaseler için yaptığın işlemleri logla deriz.
2-Master sunucudan verileri slave gönder.
3-Slave (yedek makinası) sunucuya sen slave'sin, master sunucu şu, ip'si şu, dikkate alacağın databaseler iu ve oradaki verilere ulaşmak için gerekli mysql kullanıcısı ve şifresi şu deriz.
4- master dan aldığımız veriyi slave de açarız.
5-Master'ın durumunu slave'e haber verip ikisine de hadi normal çalışmaya başlayın diyelim.
6-Master makina eşit olarak başlanan noktadan itibaran yapılan her değişikliği bir yere loglar, sonra da gider bunu slave makinada işletir. Masterdaki verilerin aynısı, anlık olarak slave'de de bulunur.

Şunu söylemek ihtiyacı duydum ki, mysql in resmi sitesinde de söylediği üzere bu bir yedekleme çözümü değil, bir parçası. Çünkü yetkisiz bir kişi master sunucuya erişim sağlayıp verileri bozarsa veya siz yanlışlıkla verilere zarar verirseniz, slave makinada da aynı bozukluğu göreceksiniz.
Başta dediğim gibi, amacım gün içinde master makinanın bir daha konuşmamak üzere "susması" durumunda kaldığım yerden devam etmek.

Şimdi yukarıdaki numaralarda gidersek;
0-
master makina'nın adresi: 23.23.23.23 olsun
Slave master'a ulaşabiliyor mu ona bakalım.
slave makinada;
telnet 23.23.23.23 3306
Sonuç olumlu olmalı.

1- Öncelikle master sunucuda gerekli ayarları yapalım.
log-bin = /var/lib/mysql/logs/mysql-bin.log
server-id=1
binlog-do-db=replike_edilecek_database

Açıklamaya gerek yok sanırım.

Şimdi master sunucuda slave sunucunun bağlanabilmesi için bir kullanıcı açalım. Bu kullanıcının yetkisinin sadece REPLICATION SLAVE olması yeterli. Tabiki ALL yetkisi de olur ama olmaması daha iyi.
Bu arada benim verileri eşitlemek için kullandığım yöntem dışında bir de verileri taşımakla uğraşmayıp, "hadi verileri master dan al gel" yöntemi var ama onun için ALL yetkisi vermek gerekiyor yeni kullanıcıya, ben de bundan hoşlanmadım, o yüzden bunu kullanıyorum.
Neyse, kullanıcıyı açalım;
mysql>GRANT REPLICATION SLAVE ON *.* TO 'replication_kullanicisi'@'%' IDENTIFIED BY 'sifre';
yetkileri güncelleyelim.
mysql>FLUSH PRIVILEGES;

Şimdi master database'in ayarları hazır, yeni ayarları yüklemek için mysql i tekrar başlatalım.
/etc/rc.d/init.d/mysqld restart

Artık bir süre master sunucuya yeni bir veri girilemesin.
mysql>FLUSH TABLES WITH READ LOCK;

2-Verileri taşıyalım. Ben mysqldump ile alıp scp ile taşıyıp diğer tarafta da açmayı tercih ediyorum.
mysqldump replike_edilecek_database -u root -p > /home/ben/replike_edilecek_database.sql;
scp /home/ben/replike_edilecek_database.sql ben@yedeksunucum.domainim.com:/home/ben
Veri orada dursun birazdan alacam.

3-slave sunucuda gerekli ayarları yapalım.
server-id=2
master-host=23.23.23.23 #master sunucumun adresi
master-connect-retry=60
master-user=replication_kullanicisi
master-password=sifre
relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index
replicate-do-db=replike_edilecek_database

Herşey açık.
Bu aşamadan şunu kontrol etmekte fayda var, masterda da slave de de /var/lib/mysql/log klasörünü tamamen boşaltmak lazım, yeni bir sunucu ise sorun yok ama daha önce bir kere denenmiş ise sorun çıkıyor, kaynaklara bakınız.

4-
mysql>create database replike_edilecek_database;
mysql -u root -p replike_edilecek_databese sql

Not: Şu anda iki sunucuda da veriler eşit durumda

5- Master'ın durumunu slave'e haber verip ikisine de hadi normal çalışmaya başlayın diyelim.

master makinada;
mysql>SHOW MASTER STATUS;
Sonuç şu şekilde olacak;
+---------------------+----------+-------------------------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------------+----------+-------------------------------+------------------+
| mysql-bin.000001 | 98 | replike_edilecek_database | |
+---------------------+----------+-------------------------------+------------------+

Slave makinada;
mysql>slave stop;
mysql>CHANGE MASTER TO MASTER_HOST='23.23.23.23', MASTER_USER='replication_kullanicisi', MASTER_PASSWORD='sifre', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=98;
mysql>slave start;

Master makinada;
mysql>unlock tables;

6- Master sunucuda yapılan bir değişiklik slave de olmalı.

Kaynaklar:
http://www.howtoforge.com/mysql_database_replication
http://aciddrop.com/2008/01/10/step-by-step-how-to-setup-mysql-database-replication/
http://www.issociate.de/board/post/17960/Problems_with_permissions_when_replicating_mysqldb_(possibly_only_a_doc_error?).html
http://wiki.kolmisoft.com/index.php/MySQL_Replication
http://dev.mysql.com/doc/refman/5.0/en/replication.html

Performans ile ilgili;
http://jcole.us/blog/archives/2006/05/25/on-disk-performance-and-mysql-replication/
http://www.mysqlperformanceblog.com/2006/05/27/jeremy-cole-on-mysql-replication/