mysql的數(shù)據(jù)同步功能,不僅在一定程度上提供數(shù)據(jù)庫查詢時的負(fù)載均衡,而且為實現(xiàn)數(shù)據(jù)庫的冗災(zāi)、備份、恢復(fù)、負(fù)載均衡等都是有極大幫助。而數(shù)據(jù)的同步功能可以通過主從復(fù)制來實現(xiàn),而主從復(fù)制是異步進(jìn)行的,并且mysql僅支持一主多從,不支持一從多主的復(fù)制模型。
1,主從復(fù)制的原理:(如下圖)
第一步:在每個更新數(shù)據(jù)的事物完成之前,主服務(wù)器都會把數(shù)據(jù)更改記錄到二進(jìn)制日志中。即使事物在執(zhí)行期間是交錯的,mysql也會串行地把事物寫入到二進(jìn)制日志中,寫入完成之后,主服務(wù)器告訴存儲引擎調(diào)交事物。
第二步:從服務(wù)器把主服務(wù)器的二進(jìn)制日志拷貝到自己的硬盤,即"中繼日志"中。首先,它啟動一個工作線程,叫I/O從線程。這個I/O線程開啟一個普通的客戶端連接,然后啟動一個特殊的二進(jìn)制日志存儲進(jìn)程(binlog dump)進(jìn)程。這個轉(zhuǎn)儲進(jìn)程從主服務(wù)器的二進(jìn)制日志中讀取事件,它不會對事物進(jìn)行輪詢。如果它跟上了主服務(wù)器,就會進(jìn)入休眠狀態(tài),并等待有新的事件發(fā)生時主服務(wù)器發(fā)出的信號,I/O線程把事件寫入到從服務(wù)器的中繼日志中。
第三步:SQL從線程讀取中繼日志,并且重放其中的事件,然后更新從服務(wù)器的數(shù)據(jù)。由于這個進(jìn)程能跟上I/O線程,中繼日志通常都在操作系統(tǒng)的緩存中,所有中繼日志的開銷很低。SQL從線程執(zhí)行的事件也可以被寫入從服務(wù)器自己的二進(jìn)制日志中或是不寫。

本文的應(yīng)用環(huán)境為:
redhat enterprise 5.4+mysql-5.5.20
主服務(wù)器:
ip地址:172.16.30.5
hostname:master.magedu.com
從服務(wù)器:
ip地址:172.16.30.6
hostname:slave.magedu.com
本文主講:
一,安裝mysql服務(wù)器
二,主從復(fù)制架構(gòu)的實現(xiàn)(兩種應(yīng)用場景)
三,主從半同步的實現(xiàn)
四,主從服務(wù)器推薦的設(shè)置
五,主主復(fù)制架構(gòu)的實現(xiàn)
一,安裝mysql服務(wù)器(在我們的主從服務(wù)器上都要這么安裝):
1,首先下載平臺對應(yīng)的mysql綠色版本至本地,這里是32位平臺:
mysql-5.5.20-linux2.6-i686.tar.gz
2、新建用戶以安全方式運行mysqld進(jìn)程:
# groupadd -r mysql
# useradd -g mysql -r -s /sbin/nologin -M mysql
# mkdir -p /mydata/data
# chown -R mysql:mysql /mydata/data
3、安裝并初始化mysql-5.5.20
# tar xf mysql-5.5.20-linux2.6-i686.tar.gz -C /usr/local
# cd /usr/local/
# ln -sv mysql-5.5.20-linux2.6-i686 mysql
# cd mysql
# chown -R mysql:mysql .
初始化mysql數(shù)據(jù)庫,指定以mysql用戶身份運行,數(shù)據(jù)庫數(shù)據(jù)存放在/mydata/data中,初始化后,mysql的root用戶默認(rèn)密碼為空:
# scripts/mysql_install_db --user=mysql --datadir=/mydata/data
# chown -R root .
4、為mysql提供主配置文件:
# cd /usr/local/mysql
# cp support-files/my-large.cnf /etc/my.cnf
#vim /etc/my.cnf
并修改此文件中thread_concurrency的值為你的CPU個數(shù)乘以2,比如這里使用如下行:
thread_concurrency = 2
另外還需要添加如下行指定mysql數(shù)據(jù)文件的存放位置:
datadir = /mydata/data
5、為mysql提供sysv服務(wù)腳本,是其能用service命令控制器啟動:
# cd /usr/local/mysql
# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
添加至服務(wù)列表:
# chkconfig --add mysqld
# chkconfig mysqld on
啟動mysql服務(wù):
#service mysqld start
為了使用mysql的安裝符合系統(tǒng)使用規(guī)范,并將其開發(fā)組件導(dǎo)出給系統(tǒng)使用,這里還需要進(jìn)行如下步驟:
6、輸出mysql的man手冊至man命令的查找路徑:
#vim /etc/man.config,添加如下行即可:
MANPATH /usr/local/mysql/man
7、輸出mysql的頭文件至系統(tǒng)頭文件路徑/usr/include:
這可以通過簡單的創(chuàng)建鏈接實現(xiàn):
# ln -sv /usr/local/mysql/include /usr/include/mysql
8、輸出mysql的庫文件給系統(tǒng)庫查找路徑:
# echo '/usr/local/mysql/lib' > /etc/ld.so.conf.d/mysql.conf
而后讓系統(tǒng)重新載入系統(tǒng)庫:
# ldconfig
9、修改PATH環(huán)境變量,讓系統(tǒng)可以直接使用mysql的相關(guān)命令:
vim /etc/profile
PATH=$PATH:/usr/local/mysql/bin
二,主從復(fù)制架構(gòu)的實現(xiàn)
注意:我們從服務(wù)器的版本要和主服務(wù)器的版本相同或高與主服務(wù)器的版本
第一種情況:
當(dāng)我們的主服務(wù)器和從服務(wù)器都是新的,主服務(wù)器中并沒有數(shù)據(jù)。
主服務(wù)器上的配置:
1,查看二進(jìn)制日志的狀態(tài),開啟二進(jìn)制日志
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
如果沒有上面顯示的off狀態(tài),則:
#vim /etc/my.cnf:
在[mysqld]的配置中,添加如下行:
log-bin=mysql-bin
2,更改mysql服務(wù)器的server id:
#vim /etc/my.cnf
在[mysqld]的配置中修改:
server-id = 1
重啟mysql服務(wù)器使生效:
#service mysqld restart
3,建立僅限slave主機(jī)使用的專門用于進(jìn)行復(fù)制數(shù)據(jù)的用戶:
mysql> grant replication client,replication slave on *.* to repl@'172.16.30.6' identified by '123456';
刷新授權(quán)表,使賬戶立即生效:
mysql> flush privileges;
4,清空日志:
mysql> flush master;
從服務(wù)器的配置:
1,開啟中繼日志:
我們也可以關(guān)閉中繼日志,由于我們的從服務(wù)器不需要時間點回復(fù)等功能,故可以關(guān)閉,減少資源浪費。但是,中繼日志是必須開啟的。
#vim /etc/my.cnf
在[mysqld]的配置中注釋掉如下行:
log-bin=mysql-bin
在[mysqld]的配置中添加如下行:
relay-log=relay-bin
2,修改server id:
server id標(biāo)識一臺mysql服務(wù)器,為了避免循環(huán)復(fù)制,主從服務(wù)器的server id必須不同
#vim /etc/my.cnf
在[mysqld]的配置中修改:
server-id = 11
重啟服務(wù)器:
# service mysqld restart
3,指定主服務(wù)器:
這里指定的要和在主服務(wù)器上建立的用戶相同:
mysql> change master to master_host='172.16.30.5',master_user='repl',master_password='123456';
4,啟動從服務(wù)器進(jìn)程并查看運行狀態(tài);
mysql> start slave;
mysql> show slave status\G
如果出現(xiàn)如下行,則表明正常啟動
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
好了,這樣我們的主從服務(wù)器就搭建好了。而通常生產(chǎn)情況下,我們是在正在使用的mysql服務(wù)器上做從服務(wù)器,這就是我們的第二種情況。
第二種情況:
為正在使用的mysql服務(wù)器做從服務(wù)器。
主服務(wù)器上的配置:
1,查看二進(jìn)制日志的狀態(tài),開啟二進(jìn)制日志
2,更改mysql服務(wù)器的server id
3,建立僅限slave主機(jī)使用的專門用于進(jìn)行復(fù)制數(shù)據(jù)的用戶
(以上三個步驟,同第一種情況的操作)
4,備份mysql數(shù)據(jù)庫中的數(shù)據(jù):
由于我們的mysql服務(wù)器處于工作狀態(tài),并且數(shù)據(jù)量通常是非常大的,故我們選擇使用熱備份,不耽誤服務(wù)器提供服務(wù),而備份之后可以直接在從服務(wù)器上導(dǎo)入。
安裝好我們的備份工具Xtrabackup,其最新版的軟件可從 http://www./software/percona-xtrabackup/ 獲得(具體的介紹使用,請看我的博客”mysql數(shù)據(jù)庫的備份與還原“)
我們首先建立一個目錄,用于存放備份的數(shù)據(jù):
#mkdir /backup
安裝xtrabackup工具:
# rpm -ivh percona-xtrabackup-2.0.0-417.rhel5.i386.rpm --nodeps
完全備份:
# innobackupex --user=DBUSER --password=DBUSERPASS /backup
# ls /backup (會生成一個時間戳的目錄,里面就是備份的數(shù)據(jù)文件)
2012-03-18_10-58-22
準(zhǔn)備完全備份文件,使完全備份文件能直接能被用作還原文件:
# innobackupex --apply-log /backup/2012-03-18_10-58-22
ok,我們的備份做好了,把它傳輸?shù)綇姆?wù)器上:
# cd /backup
# tar jcf backup.tar.gz 2012-03-18_10-58-22
# scp backup.tar.gz root@172.16.30.6:/tmp
從服務(wù)器上的配置:
1,先將主服務(wù)器備份好的數(shù)據(jù)還原
#cd /tmp
#tar xf backup.tar.gz
#cd /tmp/2012-03-18_10-58-22
找到我們做好完全備份時的二進(jìn)制日志的終止點,這個可以作為我們恢復(fù)即時點的起始點:
# cat xtrabackup_binlog_info
mysql-bin.000002 513
我們這里是完全備份的恢復(fù),要關(guān)閉服務(wù):
#service mysqld stop
請確保我們從服務(wù)器上的/mydata/data這個目錄是空的
#rm -rf /mydata/data/*
安裝好xtarbackup工具(同上),然后還原數(shù)據(jù)文件:
# innobackupex --copy-back /tmp/2012-03-18_10-58-22
更改數(shù)據(jù)文件的屬組屬主:
#cd /mydata/data
#chown -R mysql.mysql .
啟動服務(wù):
# service mysqld restart
2,開啟中繼日志:
3,修改server id:(這兩步的操作同第一種情況)
4,指定主服務(wù)器:
由于我們在主服務(wù)器上做好備份到我們把從服務(wù)器啟動這段時間,主服務(wù)器上一直有數(shù)據(jù)產(chǎn)生,故要做時間點恢復(fù),指定二進(jìn)制文件和位置:
mysql> change master to master_host='172.16.30.5',master_user='repl',master_password='123456',master_log_file='mysql-bin.000002',master_log_pos=513;
5,啟動從服務(wù)器進(jìn)程并查看運行狀態(tài);
mysql> start slave;
mysql> show slave status\G
如果出現(xiàn)如下行,則表明正常啟動
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
三,主從半同步的實現(xiàn)(只有mysql-5.5版本之后才支持)
默認(rèn)情況下我們的主從復(fù)制是異步進(jìn)行的,導(dǎo)致我們的從服務(wù)器有可能是落后于主服務(wù)器的,這在一定程度上是不安全的,如果我們的主服務(wù)器瞬間掛掉,從服務(wù)器將來不及復(fù)制數(shù)據(jù)。為了解決這個問題,我們可以打上google的一個補(bǔ)丁,使主從服務(wù)器實現(xiàn)半同步。
為什么叫半同步呢?
因為開啟這個功能之后,主服務(wù)器只等待多個從服務(wù)器中的指定的一臺從服務(wù)器復(fù)制成功,然后才進(jìn)行其他寫操作,使這個從服務(wù)器和主服務(wù)器上的數(shù)據(jù)完全同步,而并不管其他的從服務(wù)器。這在一定程度上就保證了我們數(shù)據(jù)的安全性。
當(dāng)然主服務(wù)器是不能一直等待從服務(wù)器復(fù)制成功的,因為萬一從服務(wù)器掛掉,那么主服務(wù)器將一直處于等待狀態(tài)而不提供寫服務(wù),這就需要我們定義一個超時時間,防止等待從服務(wù)器時間太長,單位是ms。如果超過定義的時間,從服務(wù)器還沒有響應(yīng),則把指定的從服務(wù)器自動降級到異步模式,在選定一個從服務(wù)器做同步。
在主服務(wù)器上配置:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000;
# vim /etc/my.cnf
在[mysqld]中添加:
rpl_semi_sync_master_enabled=1 開啟半同步功能
rpl_semi_sync_master_timeout=1000 設(shè)定超時時間為1000ms
重啟服務(wù):
#service mysqld restart
在從服務(wù)器上配置:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
# vim /etc/my.cnf
在[mysqld]中添加:
rpl_semi_sync_slave_enabled=1 開啟半同步功能
重啟服務(wù):
#service mysqld restart
查看服務(wù)是否開啟:
mysql> show flugins;
查看主服務(wù)器上的semi_sync是否開啟,注意clients 變?yōu)?,證明主從半同步復(fù)制連接成功:
mysql> SHOW GLOBAL STATUS LIKE 'rpl_semi%';
查看從服務(wù)器上的semi_sync是否開啟:
mysql> SHOW GLOBAL STATUS LIKE 'rpl_semi%';
四,主從服務(wù)器推薦的設(shè)置(如果您要做主主復(fù)制架構(gòu),這個請按需設(shè)置,但read_only絕不能設(shè)置)
主服務(wù)器上的配置:
# vim /etc/my.cnf
在[mysqld]中添加:
sync_binlog=1
任何一個事物提交之后就立即寫入到磁盤中的二進(jìn)制文件
innodb_flush_logs_at_trx_commit=1
任何一個事物提交之后就立即寫入到磁盤中的日志文件
從服務(wù)器的配置:
# vim /etc/my.cnf
在[mysqld]中添加:
skip_slave_start=1
設(shè)定從服務(wù)器開啟的時候 ,從服務(wù)器進(jìn)程不開啟,這樣可以使我們有時間對從服務(wù)器進(jìn)行配置??梢杂妹頼ysql>start slave;開啟從服務(wù)器進(jìn)程
read_only=1
設(shè)定從服務(wù)器只能進(jìn)行讀操作,不能進(jìn)行寫操作,保證數(shù)據(jù)同步(此時super用戶仍能進(jìn)行寫操作)
五,主主復(fù)制架構(gòu)的實現(xiàn)
主主復(fù)制架構(gòu),可以實現(xiàn)像主從服務(wù)器進(jìn)行寫操作,也就是說一個是另一個的主服務(wù)器,也是另一個的從服務(wù)器。
由于我們上邊已經(jīng)知道172.16.30.6為172.16.30.5的從服務(wù)器了,故我們只需知道172.16.30.5為172.16.30.6的從服務(wù)器即可。
172.16.30.5服務(wù)器的配置:
# vim /etc/my.cnf
在[mysqld]中添加:
auto-increment-increment = 2
auto-increment-offset = 1
重啟服務(wù)
# service mysqld restart
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 | 107 | | |
+------------------+----------+--------------+------------------+
172.16.30.6服務(wù)器的配置:
新建一個用于復(fù)制數(shù)據(jù)的用戶:
mysql> grant replication client,replication slave on *.* to repl@'172.16.30.5' identified by '123456';
# vim /etc/my.cnf
在[mysqld]中添加:
log-bin = mysql-bin
auto-increment-increment = 2
auto-increment-offset = 2
重啟服務(wù):
# service mysqld restart
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 107 | | |
+------------------+----------+--------------+------------------+
主從服務(wù)器接下來指定對另一臺服務(wù)器為自己的主服務(wù)器即可:
172.16.30.6服務(wù)器的指向:
mysql> stop slave;
mysql> change master to master_host='172.16.30.5',master_user='repl',master_password='123456',master_log_file='mysql-bin.000004',master_log_pos=107;
開啟從服務(wù)進(jìn)程:
mysql> start slave;
172.16.30.5服務(wù)器的指向:
mysql> change master to master_host='172.16.30.6',master_user='repl',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=107;
開啟從服務(wù)進(jìn)程:
mysql> start slave;
在172.16.30.6和172.16.30.5服務(wù)器上分別查看從服務(wù)進(jìn)程的運行狀態(tài):
mysql> show slave status\G
如果出現(xiàn)如下兩行,則說明工作正常:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
ok,我們的主主復(fù)制架構(gòu)也起來了