文章目录
- 1. 环境配置
- 2. 两台MySQL端口配置10000和10001,确认阿里云开启
- 3. 配置两台docker的server_id等配置
- 4. docker 运行两台MySQL
- 5. 配置主服务器,在主服务器新建从服务器的连接账号
- 6. 配置从服务器
- 7. 最后一步,开启同步
- 7.1 Slave_IO_Running: Yes Slave_SQL_Running: Yes同时YES才代表主从配置成功
- 7.2 从库只读设置set global read_only=1
- 8. 添加数据测试
- 8.1 测试主从同步
- 8.2 测试从库只读
- 8.3 从库不小心插入数据怎么办?
- 9. 更改MySQL8.0默认的加密方式,不然客户端连接不上
1. 环境配置
1.1 docker
1.2 Ubuntu16.04
1.3 MySQL版本是:8.0.16
2. 两台MySQL端口配置10000和10001,确认阿里云开启
2.2 为啥用10000和10001,因为3306已经开启了一个,被占用了
3. 配置两台docker的server_id等配置
3.1 新建文件夹 /root/mysql/conf/master 并添加master.cnf文件
[mysqld]
log-bin=mysql-bin-master //启用二进制日志
server_id=100 //xxx代表唯一ID,默认是1。特别注意,当前版本这里是server_id而不是server-id,有些版本可能会不一样
3.2 新建文件夹 /root/mysql/conf/slave并添加slave.cnf文件
[mysqld]
log-bin=mysql-bin-slave
server_id=200
4. docker 运行两台MySQL
4.1 以10000端口运行第一台《主》,名字是:mysql-master并挂载刚才的配置文件
4.1.1 注意挂载位置一定是刚才你新建配置文件master.cnf的位置
4.1.2 注意MySQL版本是8.0.16并且两台MySQL的版本一定要一致
docker run --name mysql-master -v /root/mysql/conf/master:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -p 10000:3306 -d mysql:8.0.16 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
4.2 以10001端口运行第2台《从》,名字是:mysql-slave并挂载刚才的配置文件
4.2.1 注意两台MySQL的用户名和密码都是root
docker run --name mysql-slave -v /root/mysql/conf/slave:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -p 10001:3306 -d mysql:8.0.16 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
5. 配置主服务器,在主服务器新建从服务器的连接账号
// 1.进入主库容器
docker exec -it mysql-master bash
// 2.登录mysql
mysql -uroot -proot
// 3.rep表示复制账号;<salve_ip>可修改为%,代表任意的主机;`IDENTIFIED BY`后面代表rep用户的认证密码
CREATE USER 'rep'@'<salve_ip>' IDENTIFIED WITH mysql_native_password BY 'reppassword';
GRANT REPLICATION SLAVE ON *.* TO 'rep'@'<salve_ip>';
5.1 推荐直接用下面的这个,因为两台MySQL在一台服务器上面
// 1.进入主库容器
docker exec -it mysql-master bash
// 2.登录mysql
mysql -uroot -proot
// 3.rep表示复制账号;<salve_ip>可修改为%,代表任意的主机;`IDENTIFIED BY`后面代表rep用户的认证密码
CREATE USER 'rep'@'%' IDENTIFIED WITH mysql_native_password BY 'rep';
GRANT REPLICATION SLAVE ON *.* TO 'rep'@'%';
5.2 获取主服务器相关信息,记录File和Position值
show master status;
+-------------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------------+----------+--------------+------------------+-------------------+
| mysql-bin-master.000003 | 656 | | | |
+-------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
6. 配置从服务器
// 1.进入从库容器
docker exec -it mysql-slave bash
// 2.登录mysql
mysql -uroot -proot
// 3.配置主库认证信息,<File>和<Position>同上
CHANGE MASTER TO MASTER_HOST='<master_ip>',MASTER_PORT=10000,MASTER_USER='rep',MASTER_PASSWORD='reppassword',MASTER_LOG_FILE='<File>',MASTER_LOG_POS=<Position>;
6.1 注意你的xxxIP一定是你的真实IP,不要因为两个在一台服务器,而设置成127.0.0.1
6.2 MASTER_LOG_FILE 和MASTER_LOG_POS设置成刚才记录的值
CHANGE MASTER TO MASTER_HOST='xxxIP',MASTER_PORT=10000,MASTER_USER='rep',MASTER_PASSWORD='rep',MASTER_LOG_FILE='mysql-bin-master.000003',MASTER_LOG_POS=656;
7. 最后一步,开启同步
在 slave 上启动线程:start slave;
查看状态
在 slave 上执行命令:show slave status\G;
7.1 Slave_IO_Running: Yes Slave_SQL_Running: Yes同时YES才代表主从配置成功
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 101.200.55.12
Master_User: rep
Master_Port: 10000
Connect_Retry: 60
Master_Log_File: mysql-bin-master.000003
Read_Master_Log_Pos: 656
Relay_Log_File: feb2e3f40b29-relay-bin.000002
Relay_Log_Pos: 329
Relay_Master_Log_File: mysql-bin-master.000003
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: 656
Relay_Log_Space: 544
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: 100
Master_UUID: 31ef5ac8-8d02-11e9-a2f6-0242ac120005
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
ERROR:
No query specified
7.2 从库只读设置set global read_only=1
- 相关命令
设置从库只读:set global read_only=1
;。1表示只读,0是读写,但对拥有super权限的账号是不生效的,所以在授权账号的时候应尽量避免添加super权限
查看读写情况:show global variables like "%read_only%";
查看server_id:show variables like '%server_id%';
- 踩坑记录
执行show slave status\G;
,发现从库并没有连接上主库,留意到错误信息大致为:“主从库server_id不能一致”,随即查看新增的master.cnf和slave.cnf,但并没有发现问题,随即用docker logs mysql-master查看启动日志,有一行警告大概是这样的:mysql: [Warning] World-writable config file ‘/etc/mysql/conf.d/master.cnf’ is ignored.,这说明配置文件并没有挂载成功,搜索后得知当文件权限全局可写时,mysql会担心这种文件被其他用户恶意修改,所以会忽略掉这个配置文件,修改文件权限chmod 644 *.cnf后,再将以上流程重新跑了一遍,问题没有复现。
8. 添加数据测试
8.1 测试主从同步
在主库 MySQL进入之后
//创建库
create database hcg;
use hcg ;
create table one(id int(10) primary key ,name varchar(11) );
show tables;
insert into one (id ,name )values (1,'hcg');
select * form one ;
# 如下:
mysql> select * from one ;
+----+------+
| id | name |
+----+------+
| 1 | hcg |
+----+------+
1 row in set (0.00 sec)
在从库查看是否有数据,先进入MySQL,发现数据自动同步过来了
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| hcg |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use hcg
Database changed
mysql> show tables ;
+---------------+
| Tables_in_hcg |
+---------------+
| one |
+---------------+
1 row in set (0.00 sec)
mysql> select * from one;
+----+------+
| id | name |
+----+------+
| 1 | hcg |
+----+------+
1 row in set (0.00 sec)
8.2 测试从库只读
在从库操作:发现数据添加上了
mysql> insert into one (id ,name )values (2,'slave');
Query OK, 1 row affected (0.00 sec)
mysql> select * from one;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
+----+-------+
2 rows in set (0.00 sec)
在主库查看:发现并没有同步过来
mysql> select * from one ;
+----+------+
| id | name |
+----+------+
| 1 | hcg |
+----+------+
1 row in set (0.00 sec)
## 同时主库插入id为2的记录
mysql> insert into one (id ,name )values (2,'slave');
Query OK, 1 row affected (0.00 sec)
mysql> select * from one;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
+----+-------+
2 rows in set (0.00 sec)
这个时候查看从库同步状态,发现报错了,怎么办,怎么办?请看下面
8.3 从库不小心插入数据怎么办?
在刚才的情况下我们已经设置了从库只读,但是还要向从库中添加数据,就会导致从库同步状态报错,如下:
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 101.200.55.12
Master_User: rep
Master_Port: 10000
Connect_Retry: 60
Master_Log_File: mysql-bin-master.000003
Read_Master_Log_Pos: 1910
Relay_Log_File: feb2e3f40b29-relay-bin.000002
Relay_Log_Pos: 1015
Relay_Master_Log_File: mysql-bin-master.000003
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table hcg.one; Duplicate entry '2' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin-master.000003, end_log_pos 1595
Skip_Counter: 0
Exec_Master_Log_Pos: 1342
Relay_Log_Space: 1798
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1062
Last_SQL_Error: Could not execute Write_rows event on table hcg.one; Duplicate entry '2' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin-master.000003, end_log_pos 1595
Replicate_Ignore_Server_Ids:
Master_Server_Id: 100
Master_UUID: 31ef5ac8-8d02-11e9-a2f6-0242ac120005
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 190613 02:01:08
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
ERROR:
No query specified
8.3.1 解决方案:
手动的解决方法是告诉从库slave_sql线程让他忽略掉这个错误继续执行:
set global sql_slave_skip_counter=1;
start slave;
上面的语句是告诉slave跳过当前卡住的event,然后重新起来干活。
8.3.2 问题解决后再次用主库添加数据测试
mysql> insert into one (id ,name )values (4,'slave');
Query OK, 1 row affected (0.00 sec)
mysql> select * from one ;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
| 3 | slave |
| 4 | slave |
+----+-------+
4 rows in set (0.00 sec)
从库查看是否同步了过来:
mysql> select * from one ;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
| 3 | slave |
| 4 | slave |
+----+-------+
4 rows in set (0.00 sec)
发现问题已经得到了解决,但是试想一下,如果我们刚才的错误不是一条而是多条怎么办?
或者说:不小心在从库添加了数据,导致从库挂掉了,但是这个时候我们不知道它挂掉了,我们依然向主库写入数据N天,这里我们模拟多向主库添加了3条数据为例
8.3.3 制造从库挂掉,主库一直塞入数据的现象
- 我们在从库中执行下面的操作
mysql> insert into one (id ,name )values (5,'slave');
Query OK, 1 row affected (0.01 sec)
mysql> select * from one;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
| 3 | slave |
| 4 | slave |
| 5 | slave |
+----+-------+
5 rows in set (0.00 sec)
mysql> show slave status\G;
## 发现从库还是正常运行的
- 然后我们在主库也同时插入这条id等于5的sql
mysql> insert into one (id ,name )values (5,'slave');
Query OK, 1 row affected (0.01 sec)
mysql> select * from one;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
| 3 | slave |
| 4 | slave |
| 5 | slave |
+----+-------+
5 rows in set (0.00 sec)
- 再次返回从库查看同步状态发现,从库挂了,但是主库依旧添加6,7,8三条数据
从库再次查看状态
mysql> show slave status\G;
## 发现从库 已经挂了
主库不理会从库,继续添加6,7,8三条数据
mysql> insert into one (id ,name )values (6,'slave');
Query OK, 1 row affected (0.00 sec)
mysql> insert into one (id ,name )values (7,'slave');
Query OK, 1 row affected (0.01 sec)
mysql> insert into one (id ,name )values (8,'slave');
Query OK, 1 row affected (0.00 sec)
mysql> select * from one ;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
| 3 | slave |
| 4 | slave |
| 5 | slave |
| 6 | slave |
| 7 | slave |
| 8 | slave |
+----+-------+
8 rows in set (0.00 sec)
8.3.4 主从库数据不一样的数据太多了怎么解决,怎么解决?
先把主库锁定FLUSH TABLES WITH READ LOCK;
不再让主库添加记录,在从库进行下面的操作:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> set global sql_slave_skip_counter=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
## 发现主从同步可以了
mysql> select * from one ;
+----+-------+
| id | name |
+----+-------+
| 1 | hcg |
| 2 | slave |
| 3 | slave |
| 4 | slave |
| 5 | slave |
| 6 | slave |
| 7 | slave |
| 8 | slave |
+----+-------+
8 rows in set (0.00 sec)
从库数据同步完之后,再把主库解锁 unlock tables;
。因为如果主从数据差距太大,从库恢复起来要很长时间,
9. 更改MySQL8.0默认的加密方式,不然客户端连接不上
通过本地去连接远程的mysql时报错,原因时mysql8.0的加密方法变了。
mysql8.0默认采用caching_sha2_password的加密方式
第三方客户端基本都不支持这种加密方式,只有自带的命令行支持
所以需要修改加密方式。
首先进入mysql命令行
[root@localhost ~]# mysql -u root -p
Enter password:
第一步:修改加密方式
ALTER USER 'root'@'%' IDENTIFIED BY 'root' PASSWORD EXPIRE NEVER;
第二步:重新修改密码
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
第三步:刷新(不做可能无法生效)
FLUSH PRIVILEGES;
之后可以成功连接。