讀寫分離與主從複製是提高mysql性能的重要及必要手段,大中型管理系統或網站必用之。php
1、什麼是讀寫分離與主從複製mysql
先看圖linux
(圖1 圖片來源於網絡)web
如上圖所示,當web server1/2/3要寫入數據時,則向mysql db Master(主服務器)發出寫入請求(即寫入到master),若是要進入讀操做時,則只向從服務器 mysql DB Slave1或2或3發出讀取請求。如此將本來讀寫在同一臺服務器的工做量分攤到了一臺負責寫入,N臺負責讀取(大部分的網站都是讀取請求遠大於寫入請求),從而從必定程度時實現了負載均衡(若是有N臺從服務器,則由主從代理系統自動分配某個具體請求從哪個從服務器讀取)。sql
讀寫分離是靠主從複製來實現的。即當一個數據寫入到主服務器後,主服務器會將寫入信息寫入到binlog(二進制日誌)裏,同時同步(或異步或半同步)到從服務器裏。從服務器根據主服務器傳來的binlog,生成relay-log(中繼日誌),而後mysql服務器再用relay-log的信息將數據寫入到數據庫。數據庫
如此作的優勢除了實現負責均衡以外,還爲咱們保留了兩份實時熱備的數據binlog和relay-log。當服務器發生災難時,咱們能夠用他們將數據恢復到任何一個時間點。centos
2、準備安全
一、在linux上安裝好兩臺mysql服務器(mysql至少5.5以上),且兩臺服務器最好在一個機房(如此經過內網進行主從複製,速度遠遠大於經過外網。若是web服務器也在同一機房,則也可內網訪問,還不用向ISP買帶寬)。服務器
假定主的IP爲10.121.0.110,從的IP爲10.121.0.220.網絡
二、關閉兩臺服務器的防火牆(稍後再配置):
# service iptables stop (這是centos6.5關閉方法,其餘系統請問度娘)
三、若是你沒有建立數據庫,則進行以下操做
(1)在主服務器上登陸mysql
# mysql -uroot -p你的密碼
(2)建立數據庫
mysql> create database test1;
mysql> create database test2;
(3)若是已經有歷史數據,則將歷史數據備份成sql文件上傳到主服務器,運行以下命令
mysql> source /disk/test1.sql;('/disk/test1.sql '換成你本身的路徑便可)
3、主服務器配置
mysql已經提供了完美的讀寫分離與主從複製支持,咱們只須要做以下設置便可。
一、配置my.cnf
# vi /etc/my.cnf
(1)去掉log-bin=mysql-bin前的「#」號。這一行的意思是容許mysql使用binlog,同時爲主從複製打開了大門。這是關鍵中的關鍵中的關鍵。
(2)若是有多個數據庫,則添加以下行:
binlog-do-db=數據庫名1
binlog-do-db=數據庫名2
binlog-do-db=數據庫名3
binlog-ignore-db=mysql(忽略mysql自身用的數據庫)
(3)查看server-id是後的數字並記住。slave(從服務器)的server-id不能與該值重複。
(4)查看expire-log-day。binlog過時時間,默認爲10天。你能夠根據你硬盤空間大小及天天產生的數據量修改。若是你有冷備,則通常設成2-3天便可。
二、操做數據庫
(1)在linux命令行下登陸mysql
# mysql -uroot -p(你的root密碼)
(2)建立並受權一個賬號
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_account'@'10.121.0.220' identified by '123456'
這句的意思是,容許從服務器'10.121.0.220 '使用'slave-account'及'123456'這個賬號密碼對對主服務器的全部數據庫(*.*)進行主從複製('REPLICATION SLAVE').
(3)重啓mysql使上述配置生效
# etc/init.d/mysql restart 或
# service mysql restart
(4)查看主服務器binlog狀態
mysql> show master stauts;
(圖2)
記下File及Position下的值。以備在配置從服務器時使用。
注:File:當前binlog的文件名,每重啓一次mysql,就會生成一個新binlog文件
Position:當前binlog的指針位置
3、從服務器配置
一、配置mysql.cnf
# vi /etc/my.cnf
(1)修改server-id=2(該值不能與主服務器的server-id同。若是有多個從服務器,則該值順延)
(2)添加以下兩行:
relay-log-index=slave-relay-bin.index (中繼日誌的索引文件)
relay-log=slave-relay-bin (中繼日誌的文件前綴)
(3)重啓mysql使上述配置生效
# /etc/init.d/mysql restart
(4)登陸mysql
# mysql -uroot -p你的密碼
(5)中止主從複製服務
mysql> stop slave
(6)主從關聯配置
mysql> change master to
master_host='10.121.0.110', #主服務器IP
master_user='slave_account ', #主服務器訪問從服務器的用戶,即上述第三條第2小條第2子條所述賬號
master_password='123456', #主服務器訪問從的密碼,即上述第三條第2小條第2子條所述密碼
master_log_file='mysql-bin.000008', #主服務器起始的binlog文件名,即圖2的file
master_log_pos=107; #主服務器binlog起始位置,即圖2的postion
上述每行都特別重要,錯一個字符都不行
(7)啓動從服務
mysql> start slave
(8) 查看從服務的狀態,判斷從服務是否生效
mysql> show slave status\G; (G參數爲縱向顯示結果)
會顯示以下結果
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.110
Master_User: slave_account
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.00008
Read_Master_Log_Pos: 107
Relay_Log_File: slave-relay-bin.000002
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.00008
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 264
Relay_Log_Space: 409
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
若是Slave_IO_Running和Slave_SQL_Running都顯示YES,則表示從與主的讀寫通信正常、主動複製已經運行,則代表咱們主從複製已經設置成功。若是出現故障,則看下節「故障排除」。
而後,你再在主服務器插入一條數據,看看從服務器相應數據庫裏有沒有作相應更新。若是有,則大功告成。
4、權限配置
雖然某些mysql版本不進行以下操做,可能也能正常運行,但我仍是強列建議你設置。不然,必有安全之慮。
一、爲master分配select、insert、update、delete權限
mysql>GRANT SELECT,INSERT,UPDATE,DELETE ON *.* TO '數據庫的賬號'@'WEB服務器的IP' identified by '密碼'。
注意,雖然master只負責寫,但也必須有select權限。緣由是使用事務時,須要從master查詢,二是update/delete這些命令都須要使用select權限。
二、爲slave分配select權限
mysql> GRANT SELECT ON *.* TO '數據庫的賬號'@'WEB服務器的IP' identified by '密碼';
這樣設置也有一個弊端,就是當主宕機時,讀寫分離機制分主動將寫操做轉到從上來,這時,就會出現寫不正常的狀況。因此,slave要分配哪些權限,還看你本身選擇。
5、防火牆配置
剛纔咱們爲了調試方便,先關閉了防火牆,但這樣作,很是很不安全。特別是數據庫服務器,關係公司的身家性命,更不可小視。
主從複製的防火牆,仍是比較好設置的,若是你只有一臺web服務器,則只須要在主、從服務器的iptables裏開放2個受權便可。先在主服務器執行以下命令:
# iptables INPUT -s 10.121.0.220 -j ACCEPT (容許從服務器訪問)
# iptables INPUT -s 10.121.2.142 -j ACCEPT (容許web服務器訪問)
# service iptables save (保存上述規則)
# service iptables restart (重啓iptables)
在從中將第一條換成主的IP便可。
設置完後,再在從上用show slave status看看主從複製是否正常。
6、一些故障排除
設置過程當中,可能會出現以下幾個故障
(1) Slave_IO_Running: No
(2) Slave_IO_Running: Connect
(3)Last_IO_Error: error connecting to master 'slave-account@192.168.0.110:3306' - retry-time: 60 retries: 8640
其實上述故障,都是由IO不正常形成的,請從以下幾個步驟着手檢查。
a.配置完主或從的my.cnf後,是否重啓了mysql服務。若是重啓還不成功,則能夠用reboot命令重啓服務器後再試
b.change master那一步所填寫的信息是否正確。
(4)Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).
如上是說主、從使用了相同的server-id,進入my.cnf檢查,改正之,而後重啓mysql服務。
7、php設置
在php的數據庫鏈接配置文件裏做以下設置便可
//該行讀寫分離支持
'DB_DEPLOY_TYPE'=> 1,
'DB_RW_SEPARATE'=>true,
//主、從數據庫的IP地址,前爲主,後從
'DB_HOST' => '10.121.0.110,10.121,0.220',
// 數據庫類型
'DB_TYPE' => 'mysql',
// 用戶名,若是主和從的用戶名相同,則 可省略一個
'DB_USER' => 'root root',
// 用戶名,若是主和從密碼相同,則可省略一個
'DB_PWD' => '123456 123456',
// 用戶名,若是主和從數據庫相同,則可省略一個
'DB_NAME' => 'test test',
其餘設置請參照本人的《使TP框架在主從複製下「支持事務」》
(該文系HANYUCQ原創,歡迎轉載,但請保留該信息。)