關(guān)于主從同步的背景:
最近在工作上遇到一個任務(wù):將主服務(wù)器上的mysql數(shù)據(jù)庫和從服務(wù)器的mysql數(shù)據(jù)庫實現(xiàn)主從同步。即當主庫發(fā)生數(shù)據(jù)的變更時,從庫也能做出同樣的變更。
1.環(huán)境:Linux, docker;
2.mysql運行在docker容器中;
找到mysql的配置文件
MySQL默認讀取的配置文件是“my.cnf”,這個文件的位置可以通過以下命令查找:
$ mysql --help|grep 'my.cnf'
該查找命令會返回以下路徑,排序靠前的路徑會被優(yōu)先讀取,若文件不存在則往下讀:
order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
我的my.cnf文件在路徑/etc/mysql下,文件內(nèi)容是這樣的:
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
#******
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
“!includedir /etc/mysql/conf.d/” 表示my.cnf配置文件中引入了/etc/mysql/conf.d/目錄下所有的文件內(nèi)容,因此在該目錄下的文件中添加配置內(nèi)容也能達到配置的作用。
由于修改配置文件極有可能將容器掛掉,無法進入容器從而無法把配置文件復原,因此,在最初創(chuàng)建這個容器的時候,出于安全考慮,我將宿主機的/home/mysql/conf/目錄掛載到了容器的/etc/mysql/conf.d/目錄中。這樣,即使無法進入容器也可以在宿主機的掛載目錄中找到對應(yīng)的配置文件進行復原。
解決過程
a.主庫和從庫(master & slave)
我的主庫和從庫所在服務(wù)器分別在不同的服務(wù)器的docker中,mysql在容器的3306端口,對應(yīng)著宿主機的3306端口
1.主庫:10.30.129.204
2.從庫:10.30.129.191
b.主庫的配置
在主庫的配置文件中添加以下內(nèi)容:
[mysqld]
server_id=100 #服務(wù)器標志號,與從庫的server_id標識不得和主庫一致
log-bin=mysql-bin #設(shè)置日志文件,從庫的I/O線程通過讀這個文件的日志實現(xiàn)同步
binlog_cache_size=1M #日志的緩存大小
binlog_format=mixed #設(shè)置bin-log日志文件格式為:mixed,防止主鍵重復
slave_skip_errors=1062 #忽略所有的1062錯誤
expire_logs_days=7 #設(shè)置bin-log日志文件保存的天數(shù)
配置完成后回到宿主機上,重啟mysql:
>docker restart mysql
重啟后進入容器,在mysql shell環(huán)境下查看主庫的狀態(tài):
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
在這里記錄下日志文件mysql-bin.000001和日志記錄到的Position,在從庫連接時需要用到。
除此之外,還需要在主服務(wù)器上添加一個用于從機訪問的帳號, 賦予REPLICATION SLAVE權(quán)限:
GRANT REPLICATION SLAVE ON *.* TO '<SLAVE_NAME>'@'<SLAVE_ADDRESS>' IDENTIFIED BY '<PASSWORD>';
稍后,<SLAVE_NAME>和<PASSWORD>將會在從庫的配置中使用。
c.從庫的配置
和主庫的配置過程一樣,先將宿主機的相關(guān)目錄掛載到配置文件所在的目錄上,以防不測?,F(xiàn)在我們來修改從庫的配置文件,在配置文件中添加以下內(nèi)容:
[mysqld]
server_id=101 #必須和主服務(wù)器不一致
slave_skip_errors=1062
relay_log=mysql-relay-bin #設(shè)置中繼日志
log_slave_updates=1
log_error=mysql_log_error #設(shè)置錯誤日志,當主從同步的過程中出現(xiàn)錯誤可以翻日志
master-host=10.30.129.204
master-user=<SLAVE_NAME>
master-password=<PASSWORD>
master-port=3306
配置完成后,在從服務(wù)器上重啟一下mysql:
docker restart mysql
然后進入mysql shell中輸入以下命令:
mysql> change master to
master_host='10.30.129.204', #主服務(wù)器地址
master_user='<SLAVE_NAME>',
master_password='<PASSWORD>',
master_port=3306,
master_log_file='mysql-bin.000001', #先前記錄的主庫日志文件名
master_log_pos=154; #日志給從庫I/O線程讀取的起始位置
開啟同步:
mysql> start slave;
最后,查看從庫同步的狀態(tài):
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.30.129.204
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 50325805
Relay_Log_File: mysql-relay-bin.000007
Relay_Log_Pos: 50325971
Relay_Master_Log_File: mysql-bin.000001
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: 50325805
我們只需要關(guān)注以下幾個指標:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Master_Log_File: mysql-bin.000001
Relay_Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 50325805
Exec_master_log_pos: 50325805
日志文件和記錄位置必須是兩兩一致的,IO線程和SQL線程都要是Yes狀態(tài)。若同步失敗,可以在錯誤日志下排查一下。到這里的時候,mysql的主從同步就大功告成了。
注意事項
1.主庫中原先就有數(shù)據(jù)
如果主庫中原來就存在數(shù)據(jù),并且需要將先前的數(shù)據(jù)同步到從庫中,可以全量備份數(shù)據(jù)庫到從庫。通過以下命令導出和導入:
#全量導出
mysqldump -h <host> -u <username> -p <password> --all-databases >all-databases.sql
#全量導入(在從庫的mysql shell環(huán)境下)
mysql> source
2.主庫一直有新數(shù)據(jù)的更新
在從主庫備份全庫數(shù)據(jù),到查看主庫mysql-bin-log日志文件的記錄位置position的這段時間里,如果數(shù)據(jù)庫被別的用戶寫入數(shù)據(jù),會導致主從不一致的情況。安全起見,可以在備份前鎖庫,待記錄完日志文件狀態(tài)后再解鎖:
#加鎖
mysql> FLUSH TABLES WITH READ LOCK;
#解鎖
mysql> UNLOCK TABLES;