### 文档目标
由于集群模式容易出现脑裂,恢复起来速度慢,难度大,不稳定,所以采用主从模式托管,容易恢复,更加稳定,同时建立成功主从模式以后,及时关机再重启也不会丢失主从状态。
通过本文档可以把mariadb或mysql从三节点集群模式切换为互为主从(成环)
- 相对于集群的好处就是不会发生脑裂,故障恢复相对比较容易
- 坏处是如果挂掉一个节点时,剩下的两个节点就会变成主从模式,如果应用读写到从节点,那么数据就不同步了,需要等待恢复以后才能自动同步(所以我们要控制,挂掉一个节点后,让读写正确的切换到主节点上,可能要`keepalived`、`haproxy`的配合)
[TOC]
### 0、检查是否是集群状态
ps: 监测当前是否是集群模式, 而且整个集群的所有服务器正常,如果不是 `ON` ,则停止操作,并联系管理员。
**在集群中所有服务器上执行**
``` sql
MariaDB [(none)]> show global variables like '%wsrep_on%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wsrep_on | ON |
+---------------+-------+
1 row in set (0.00 sec)
```
### 1、停止所有写入
**在集群所有服务器上执行此步**
**在集群所有服务器上执行此步**
**在集群所有服务器上执行此步**
如果 `mariadb` 是通过 `hosts` 文件中的域名进行访问的,那么只需要编辑 `/etc/hosts` , 把 `mysql.cloud.local` 的域名解析删掉就可以停止所有读写,执行以下命令。
``` BASH
cp /etc/hosts /etc/hosts.bak
sed -i "/mysql.cloud.local/d" /etc/hosts
```
等待1分钟,依次进入集群中所有的 `mariadb` ,查看进程状态,确保没有额外的读写操作( `command` 列除了 `show processlist` 外没有多余的 `sleep` 和 `query` )。
``` sql
MariaDB [(none)]> show processlist;
```
### 2、添加一个专门用来同步的用户
在节点1中的 `mariadb` 执行以下命令,如果全部输出ok,则继续。
``` BASH
/usr/local/mariadb/bin/mysql -A -e "GRANT replication slave ON *.* TO 'rep'@'%' IDENTIFIED BY '123456'; flush privileges;"
mysql -A -urep -p123456 -e "select 'ok';"
```
依次在第二台、第三台上重复此操作
### 3、设置所有集群中的节点为只读。
进入节点1中的 `mariadb` 执行以下命令
``` sql
flush table with read lock;
```
依次在第二台、第三台上顺序重复此操作
### 4、停止集群
如果你使用的是`supervisor`守护`mariadb`,则
``` BASH
supervisorctl stop mariadb
```
如果你使用的是`systemctl`托管,则
``` BASH
systemctl stop mariadb
```
此时节点应该自动停止了,检查是否没有 `mariadb` 和 `mysql` 进程,如果有按需求判断是否停掉。
``` BASH
ps -ef | grep -E "mariadb|mysql"
```
如果没有停止,则执行以下命令停止
``` BASH
/usr/local/mariadb/bin/mysqladmin shutdown
```
依次在第二台、第三台上顺序重复[4、停止集群](#4停止集群)操作
### 5、配置集群中每个节点为单点
执行下面命令改为单点(注意现在不启动),执行完检查是不是变成了 `wsrep_on=OFF`
``` BASH
sed -i "s/^wsrep_on=.*/wsrep_on=OFF/g" /etc/my.cnf.d/server.cnf
```
创建`relaylog`日志存储的目录,用来防止同步波动缓存同步信息。
``` BASH
mkdir /data/mariadb/relaylog
chown -R mysql.mysql /data/mariadb/relaylog/
```
添加配置到 `[mysqld]` 配置节中(**注意现在不启动**),该配置表示我们只同步 `cloud` 库和其下的表,如果要同步更多的库和表可以用逗号分隔,追加。
如果想了解各个参数是什么含义可以到本小册 [relaylog](https://www.kancloud.cn/coding3min/playdb/1760394)里看
``` BASH
vim /etc/my.cnf.d/server.cnf
# 添加内容如下
replicate-do-db=cloud #cloud是你想同步的库名,如果有多个请用逗号隔开
log-slave-updates
replicate-wild-do-table=cloud.% #cloud是你想同步的库名,cloud.% 代表这个库下面的所有表,如果有多个请用逗号隔开
binlog-ignore-db=mysql # 忽略mysql库
max_relay_log_size = 0
relay_log=/data/mariadb/relaylog/relay-bin #请设置成正确的目录,上面刚刚创建的那个,最后的relay-bin是文件前缀
relay_log_purge = 1
relay_log_recovery = 1
sync_relay_log =0
sync_relay_log_info = 0
slave-skip-errors=1032,1062,1053,1146,2003
```
参考添加成功的图片

依次在第二台、第三台上顺序重复[5、配置集群中每个节点为单点](#5配置集群中每个节点为单点)操作
### 6、建立 `2同步3` 主从结构
假如是三节点主从,我们使用 `1同步2` , `2同步3` , `3同步1` 的方案,现在三台机器上的 `mariadb` 都是停止状态的。
`2同步3` ,所以 `3` 是主节点, `2` 是从节点。
逆序启动,并建立主从
**启动节点3**
``` BASH
mkdir -p /var/run/mariadb; chown -R mysql:mysql /var/run/mariadb; /usr/local/mariadb/bin/mysqld_safe --datadir=/data/mariadb/data --pid-file=/var/run/mariadb/mariadb.pid > /dev/null 2>&1 &
```
**获取同步主节点的关键信息**
进入主【节点3】数据库中,执行命令
``` sql
unlock tables;
show master status;
```
得到同步主节点的关键信息

**启动节点2**
``` BASH
mkdir -p /var/run/mariadb; chown -R mysql:mysql /var/run/mariadb; /usr/local/mariadb/bin/mysqld_safe --datadir=/data/mariadb/data --pid-file=/var/run/mariadb/mariadb.pid > /dev/null 2>&1 &
```
**建立主从结构**
进入从【节点2】中的数据库,指定主库信息,完成主从关系建立(注意:节点3的ip地址别忘记替换,使用 `eth0` 本地网卡的 `ip` ,不要使用浮动 `ip` ,也不要使用 `vip` )
``` sql
unlock tables;
CHANGE MASTER TO
MASTER_HOST='节点3的ip地址',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000171',
MASTER_LOG_POS=33105258;
start slave; #开始同步
```
查看slave的状态,注意查看slave的进程状态,下面红色方框中圈起来的是两个 `Yes` 就表示状态正常了,注意等待主库复制的延迟秒数变为0 `Seconds_Behind_Master: 0`
``` sql
show slave status \G
```

### 7、测试 `2同步3` 主从同步状态
**进入主节点3的数据库中,执行sql命令,创建一个测试表。**
``` sql
use cloud;
CREATE TABLE IF NOT EXISTS `testrep` (
`xx_id` INT UNSIGNED AUTO_INCREMENT,
PRIMARY KEY ( `xx_id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
show tables like "testrep";
```
结果如下则创建成功
``` sql
MariaDB [cloud]> show tables like "testrep";
+---------------------------+
| Tables_in_cloud (testrep) |
+---------------------------+
| testrep |
+---------------------------+
1 row in set (0.00 sec)
```
进入从节点2的数据库上,再执行查询命令查看同步状态,如果同上面结果一样则表示主从建立成功
``` sql
use cloud;
show tables like "testrep";
```
### 8、建立 `1同步2` 主从结构
同上面类似,只不过是在 `1` 和 `2` 节点上执行而已。
要注意四个点!!!
* 重复 `6` 和 `7` 两步,把【主节点3】和【从节点2】换成【主节点2】和【从节点1】
* 注意此时节点2已经启动了 **不要再重复启动节点**
* `unlock tables;` 重复执行无所谓
* 步骤【 `7` 主从同步状态】不要再重复创建测试表了,主从建立成功后直接查看【从节点 `1` 】中是否有 `testrep` 表就可以了
### 9、建立 `3同步1` 主从结构
同上面类似,只不过是在 `3` 和 `1` 节点上执行而已。
要注意四个点!!!
* 重复 `1.6` 即可,把【主节点3】和【从节点2】换成【主节点1】和【从节点3】
* 注意此时所有节点都已经启动了 **不要再重复启动节点**
**测试同步状态**
在节点1上执行命令
``` sql
MariaDB [(none)]> use cloud;
Database changed
MariaDB [cloud]> drop table testrep;
Query OK, 0 rows affected (0.01 sec)
MariaDB [cloud]> show tables like "testrep";
Empty set (0.00 sec)
```
在节点3和节点2和执行以下命令,如果结果都是 `Empty set` ,表示三节点主从模式建立成功。
``` sql
MariaDB [cloud]> show tables like "testrep";
Empty set (0.00 sec)
```
### 10、恢复域名解析
在全部服务器上执行
``` BASH
cp /etc/hosts.bak /etc/hosts
```