MySQL集羣解決方案(一):主從複製

準備

我是在CentOS上使用docker部署,因此需要提前準備與docker相關的操作.

docker

CentOS安裝

配置

映射

一個主機對多個虛擬機,所以需要使用不同的具名配置文件夾,比如/etc/mysql/my.cnf.d/master01來做不同mysql-docker實例的啓動項的配置區分.除此之外還有數據文檔配置的區分:/var/lib/mysql/master01

mysql-docker一般默認的數據及啓動項配置分別對應/var/lib/mysql/etc/my.cnf.d,對應起來就是如下關係:

/etc/mysql/my.cnf.d/master01:/etc/my.cnf.d
/var/lib/mysql/master01:/var/lib/mysql

可能涉及創建文件夾

mkdir -p /etc/mysql/my.cnf.d/master01 /var/lib/mysql/master01
# 權限設置要嚴格,否則有些配置文件,比如my.cnf會失效
chmod 645 -R /etc/mysql/my.cnf.d/master01
chmod 777 -R /var/lib/mysql/master01

端口

默認是3306,我映射爲6306

鏡像

理論上是選擇mysql的鏡像,但本次是爲搭建PXC(Percona XtraDB Cluster)集羣做準備的,那麼選擇percona:5.7.23

percona是啥

權限

這裏指的是root用戶的初始密碼如何定義和設置的問題,可以有三種選擇,三選一:

  1. 無密碼: MYSQL_ALLOW_EMPTY_PASSWORD=true

  2. 指定密碼: MYSQL_ROOT_PASSWORD=XXX, 推薦.

  3. 隨機密碼: MYSQL_RANDOM_ROOT_PASSWORD=true.

    不推薦! 因爲這意味着需要自己重置密碼,並且需要預先在my.cnf[mysqld]下配置skip-grant-tables,自己定義密碼後還需要重啓,比較麻煩.

啓動

主節點

創建容器

以上準備工作大致勾勒出了容器創建命令:

docker create --name percona-master01 -v /var/lib/mysql/master01:/var/lib/mysql -v /etc/mysql/my.cnf.d/master01:/etc/my.cnf.d -p 6306:3306 -e MYSQL_ROOT_PASSWORD=master01 percona:5.7.23

my.cnf

要做集羣,首先至少需要配置如下幾項:

  1. 開啓log-bin
  2. 設置server-id

所以在對應目錄/etc/mysql/my.cnf.d/master01下創建my.cnf並寫入:

[mysqld]
log-bin=mysql-bin
server-id=1
sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

這裏的sql_mode是爲了解決可能出現的1055錯誤的,與是否配置集羣無關.

提供一下初始化的便捷腳本:

cat << EOF > /etc/mysql/my.cnf.d/master01/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1
sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
EOF

啓動鏡像

運行master01並查看日誌:

docker start percona-master01  && docker logs -f percona-master01

驗證

等待啓動完成後,可以先在宿主機上查看相應的配置是否生效,比如log-bin:

ll /var/lib/mysql/master01 | grep mysql-bin

或者直接登錄驗證,可以連接宿主機端口,也可以連接docker虛擬機,不過需要先查詢它的IP.

  1. 宿主機
# 不能省略-h127.0.0.1,否則會認爲是localhost而拒絕登錄
mysql -h127.0.0.1 -P6306 -uroot -pmaster01 -Dmysql
  1. 虛擬機
docker exec -it percona-master01 mysql -uroot -pmaster01 -Dmysql 

授權

此時服務端就搭建好了,也連接上了,還需要做些初始化操作,比如創建用戶pxc並賦予權限.

可以在服務端,也可以在客戶端連接並操作.無論是服務端還是客戶端,實際的sql操作自然不變.

以創建集羣用戶,賦予權限和查看集羣狀態的核心sql爲例:

use mysql;
create user 'pxc'@'%' identified by 'pxc';
grant replication slave on *.* to 'pxc'@'%';
flush privileges;

重啓後執行:

# 查看集羣狀態
show master status;
# 查看二進制日誌相關的配置項
show global variables like 'binlog%';
# 查看server相關的配置項
show global variables like 'server%';

小結

不論怎麼連,只要是命令就可以使用shell腳本一條一條實現比如創建用戶

# -D數據庫名 -e需要執行的SQL腳本
mysql -h127.0.0.1 -P6306 -uroot -pmaster01 -Dmysql -e"create user 'pxc'@'%' identified by 'pxc';"

從節點

與主節點的配置大致相同,這裏只列出關鍵配置的區別.

權限設置要嚴格,否則有些配置文件,比如my.cnf會失效

bash-4.2$ mysql -uroot -p
mysql: [Warning] World-writable config file '/etc/my.cnf.d/my.cnf' is ignored.
mysql: [Warning] World-writable config file '/etc/mysql/my.cnf' is ignored.
mkdir -p /etc/mysql/my.cnf.d/slave01 /var/lib/mysql/slave01
chmod 644 -R /etc/mysql/my.cnf.d 
chmod g+w,o+w -R /var/lib/mysql

my.cnf

仍然採用相同的思路在/etc/mysql/my.cnf.d/slave01下創建my.cnf並寫入:

[mysqld]
# 服務ID,不與master重複即可
server-id=2
sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
docker create --privileged --name percona-slave01 -v /var/lib/mysql/slave01:/var/lib/mysql -v /etc/mysql/my.cnf.d/slave01:/etc/my.cnf.d -p 6307:3306 -e MYSQL_ROOT_PASSWORD=slave01 percona:5.7.23
docker start percona-slave01  && docker logs -f percona-slave01
mysql -h0.0.0.0 -P6307 -uroot -pslave01 -Dmysql

查看主節點(端口是6306)的二進制日誌(bin-log)信息:

mysql -h0.0.0.0 -P6306 -uroot -pmaster01 -Dmysql -e'show master status;'

輸出如下:

+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

關聯主節點

CHANGE MASTER TO
master_host='192.168.0.122',
master_user='pxc',
master_password='pxc',
master_port=6306,
master_log_file='mysql-bin.000001',
master_log_pos=154;
start slave;
show slave status;

啓動從節點並查看從節點狀態

start slave;
show slave status;

master02和slave02搭建的命令瀑布

這裏是記錄下自己完整的操作過程,不要直接執行.

#!/bin/bash

###### master02 ###### 

mkdir -p /etc/mysql/my.cnf.d/master02 /var/lib/mysql/master02
chmod 645 -R /etc/mysql/my.cnf.d/master02
chmod 777 -R /var/lib/mysql/master02

docker create --name percona-master02 -v /var/lib/mysql/master02:/var/lib/mysql -v /etc/mysql/my.cnf.d/master02:/etc/my.cnf.d -p 7306:3306 -e MYSQL_ROOT_PASSWORD=master02 percona:5.7.23

cat << EOF > /etc/mysql/my.cnf.d/master02/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=10
sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
EOF

docker start percona-master02 && docker logs -f percona-master02

docker exec percona-master02 mysql -uroot -pmaster02 -e"show variables like 'log_bin'"
docker exec percona-master02 mysql -uroot -pmaster02 -e"show master status;"
docker exec percona-master02 mysql -uroot -pmaster02 -e"show global variables like 'server%';"

docker exec percona-master02 mysql -uroot -pmaster02 -Dmysql -e"create user 'pxc'@'%' identified by 'pxc';"
docker exec percona-master02 mysql -uroot -pmaster02 -Dmysql -e"grant replication slave on *.* to 'pxc'@'%';"
docker exec percona-master02 mysql -uroot -pmaster02 -Dmysql -e"flush privileges;"


###### slave02 ######
mkdir -p /etc/mysql/my.cnf.d/slave02 /var/lib/mysql/slave02
chmod 645 -R /etc/mysql/my.cnf.d/slave02
chmod 777 -R /var/lib/mysql/slave02

docker create --name percona-slave02 -v /var/lib/mysql/slave02:/var/lib/mysql -v /etc/mysql/my.cnf.d/slave02:/etc/my.cnf.d -p 7307:3306 -e MYSQL_ROOT_PASSWORD=slave02 percona:5.7.23

cat << EOF > /etc/mysql/my.cnf.d/slave02/my.cnf
[mysqld]
server-id=12
sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
EOF

docker start percona-slave02

docker exec percona-slave02 mysql -uroot -pslave02 -e"CHANGE MASTER TO master_host='192.168.0.122', master_user='pxc', master_password='pxc', master_port=7306, master_log_file='mysql-bin.000003', master_log_pos=154;start slave;"
docker exec percona-slave02 mysql -uroot -pslave02 -e"start slave;"
docker exec percona-slave02 mysql -uroot -pslave02 -e"show slave status;"

缺點

如果不小心在slave節點上進行寫操作,就會出現同步失效問題,兩種解決方案:

  1. 手動同步主節點的log_bin
    此時執行show slave status;會得到如下結果:Slave_SQL_Running:No,解決辦法是手動同步,也就是根據master當前的日誌位置,重新執行change master操作.
  2. 架構變更
    1. 使用Mycat實現讀寫分離
    2. 改爲HAProxy+Mycat+PXC方式,使得每個節點都可讀可寫.

參考

  1. mysql shell腳本
  2. Percona 數據庫
  3. MySQL同步故障:" Slave_SQL_Running:No" 兩種解決辦法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章