查看服務(wù)器環(huán)境
主從兩臺(tái)MySQL服務(wù)器均使用以下環(huán)境。
shell > lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.3.1611 (Core)
Release: 7.3.1611
Codename: Core
查看MySQL版本
shell > mysql -u root -p
// 服務(wù)器 A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 128
Server version: 5.7.18-log MySQL Community Server (GPL)
// 服務(wù)器 B
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 5.7.19-log MySQL Community Server (GPL)
觀察到服務(wù)器版本略有差異,應(yīng)用在生產(chǎn)環(huán)境時(shí)最好將MySQL的版本保持一致。最不濟(jì)也要保證前兩位(5.7)版本保持一致,不要出現(xiàn)主(5.7)從(5.1)這種跨版本的情況。
設(shè)置復(fù)制主機(jī)配置
要配置主機(jī)以使用基于二進(jìn)制日志文件位置的復(fù)制,您必須啟用二進(jìn)制日志記錄并建立唯一的服務(wù)器ID。
shell > service mysqld stop
關(guān)閉 mysqld 服務(wù) 并 編輯 my.cnf ,配置 server-id 時(shí)需要注意:此ID用于標(biāo)識(shí)組內(nèi)的各個(gè)服務(wù)器,并且必須為1到(2 32)-1 之間的正整數(shù)。
[mysqld]
log-bin = mysql-bin
server-id = 1
read-only = 0 # 主庫讀寫都可以
binlog-do-db = test # 需要備份的庫,多個(gè)庫寫多行
binlog-ignore-db = mysql # 無需備份的庫,多個(gè)庫寫多行
注意:test 庫是一個(gè)新庫。采用新庫的目的是避免主從庫的結(jié)構(gòu)、數(shù)據(jù)的不同導(dǎo)致主從復(fù)制失敗。實(shí)際在生產(chǎn)環(huán)境下,主從庫結(jié)構(gòu)數(shù)據(jù)同步這步是漏不掉的。
創(chuàng)建用戶進(jìn)行復(fù)制
任何一個(gè)已被授予 REPLICATION SLAVE 權(quán)限的用戶都可以連接到主機(jī)并執(zhí)行復(fù)制操作??梢詫iT為為每個(gè)從機(jī)創(chuàng)建復(fù)制帳戶,也可以多個(gè)從機(jī)使用一個(gè)帳戶。但需要注意的是僅授予其復(fù)制過程中需要的權(quán)限(白名單原則),以減少因此引入的危害。
[mysql] > CREATE USER 'repl'@'slave-ip-address' IDENTIFIED BY 'slave-password';
[mysql] > GRANT REPLICATION SLAVE ON *.* TO 'repl'@'slave-ip-address';
需要注意:
slave-ip-address 表示 從機(jī)服務(wù)器的ip地址;
slave-password 表示 從機(jī)新用戶的密碼;
復(fù)制主二進(jìn)制日志坐標(biāo)
MySQL [(none)]> use mysql;
MySQL [mysql]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000016 | 154 | test | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
生成數(shù)據(jù)快照
使用mysqldump創(chuàng)建數(shù)據(jù)快照。當(dāng)主庫與從庫之間信息不對(duì)等時(shí),可以在啟動(dòng)復(fù)制之前先將主庫數(shù)據(jù)導(dǎo)入到從庫。
mysqldump -u root -p --databases test --master-data > dbdump.db
-
--databases test表示只選擇 test 庫 -
--ignore-table選項(xiàng)排除數(shù)據(jù)庫中的所有表 。 - 更多信息可以參考鏈接:選擇數(shù)據(jù)快照的方法。
設(shè)置復(fù)制從站
[mysqld]
server-id = 2
要注意 server-id與其它主機(jī)或從機(jī)均不同。修改完需要重啟mysqld??梢圆粏⒂迷搹臋C(jī)的二進(jìn)制日志功能,除非它需要作為其它從機(jī)的主機(jī)。
在從站上設(shè)置主站配置
要設(shè)置從站與主站進(jìn)行通信以進(jìn)行復(fù)制,請(qǐng)使用必要的連接信息配置從站。為此,請(qǐng)?jiān)趶恼旧蠄?zhí)行以下語句,將選項(xiàng)值替換為與系統(tǒng)相關(guān)的實(shí)際值:
MySQL [mysql]> CHANGE MASTER TO
-> MASTER_HOST = '主庫IP地址',
-> MASTER_USER = 'repl',
-> MASTER_PASSWORD = '主庫用戶repl的密碼',
-> MASTER_LOG_FILE = 'mysql-bin.000016',
-> MASTER_LOG_POS = 154;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
MASTER_LOG_FILE與MASTER_LOG_POS可見上面復(fù)制主二進(jìn)制日志坐標(biāo)查詢出的結(jié)果。
最后啟動(dòng)從服務(wù)器,執(zhí)行此過程后,從服務(wù)器連接到主服務(wù)器,并復(fù)制從快照?qǐng)?zhí)行以來在主服務(wù)器上發(fā)生的任何更新。
MySQL [mysql]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
最后檢查是否主從復(fù)制配置生效
查看從機(jī)的狀態(tài),如果Slave_IO_Running與Slave_SQL_Running都是Yes則說明主從配置成功。
MySQL [mysql]> SHOW SLAVE STATUS\G;
//...
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
//...
如果出現(xiàn)一直Connecting則需要進(jìn)行排查。查看從機(jī)的錯(cuò)誤日志,位置可以通過查看文件/etc/my.cnf得到錯(cuò)誤日志的位置。
tail -f /data/mysql/mysql-error.log
2017-08-07T09:29:39.327901Z 18 [ERROR] Slave I/O for channel '': error connecting to master 'repl@47.**.**.**:3306' - retry-time: 60 retries: 38, Error_code: 1130
遇到錯(cuò)誤可以查看MySQL錯(cuò)誤碼清單(服務(wù)端),MySQL錯(cuò)誤清單(客戶端)依據(jù)錯(cuò)誤碼可以方便的定位錯(cuò)誤。
我的錯(cuò)誤排查過程
Error_code: 1130
我遇到的錯(cuò)誤是Error_code: 1130,對(duì)應(yīng)的解釋是Message: Host '%s' is not allowed to connect to this MySQL server。
原因是我配置連接主庫時(shí),我錄入的是從庫的ip地址。所以導(dǎo)致從庫嘗試連接從庫,但是使用的是從庫不存在的用戶。所以即報(bào)了上述錯(cuò)誤。
Error_code: 2003
修改完上述問題后,又出現(xiàn)Error_code: 2003,對(duì)應(yīng)的解釋是Message: Can't connect to MySQL server on '%s' (%d)。
1)檢查主機(jī)是否開啟tcp連接。
lsof -i tcp:3306
如果沒有tcp連接,則需要去/etc/my.cnf中設(shè)置bind-address = 0.0.0.0。
2)檢查主機(jī)防火墻是否攔截了該連接。
service iptables stop
在測試遠(yuǎn)程連接mysql -u repl@'%' -p -P3306 -h 47.**.**.**;,登錄正常。
無論是測試環(huán)境還是生產(chǎn)環(huán)境,關(guān)閉iptables只為取悅mysql都是不恰當(dāng)?shù)淖龇?。所以我們需要為特定?code>ip地址開放3306端口,有關(guān)安全方面都建議使用最小權(quán)限原則(白名單)。
# 僅允許指定ip地址
iptables -A INPUT -p tcp --dport 3306 -s 47.**.**.** -j ACCEPT
# 保存規(guī)則
/sbin/service iptables save
# 重啟iptables
service iptables restart
- CentOS下針對(duì)iptables管理,可以參考 《Saving IPTables Rules》。
- 有關(guān)iptables的基本操作,可以參考《Guide to Using Iptables》。
