当然如果是win10搭建MySQL8.0,一条主机搭建主从也是可以的,可以参考win10搭建主从
如下是我的主服务器配置
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# 设置3308端口
port = 3308
#唯一,要与从机的不同
server-id = 1
# Binary Logging.
#开启二进制日志
log-bin= mysql-bin-master
# 设置mysql的安装目录
basedir=D:\\mysql\\mysqlMaster
# 设置 mysql数据库的数据的存放目录,MySQL 8+ 不需要以下配置,系统自己生成即可,否则有可能报错
# datadir=D:\\mysql\\mysqlMaster\\data
# 允许最大连接数
max_connections=200
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
从服务器配置
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# 设置3309端口
port = 3309
log-bin=mysql-bin-slave
server_id=200
# 设置mysql的安装目录
basedir=D:\\mysql\\mysqlSlave
# 设置 mysql数据库的数据的存放目录,MySQL 8+ 不需要以下配置,系统自己生成即可,否则有可能报错
# datadir=D:\\mysql\\mysqlSlave\\data
# 允许最大连接数
max_connections=20
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
[mysqld]
log-bin=mysql-bin-master //启用二进制日志
server_id=100 //xxx代表唯一ID,默认是1。特别注意,当前版本这里是server_id而不是server-id,有些版本可能会不一样
[mysqld]
log-bin=mysql-bin-slave
server_id=200
PS: 如果是在Windows上面安装的docker-desktop安装的则在自己的盘下面建两个文件夹也是可以的,比如我的是:
D:/SoftTools/docker/master
和D:/SoftTools/docker/slave
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
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
如果是windows安装的dockers,则可以
docker run --name mysql-master -v D:/SoftTools/docker/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
docker run --name mysql-slave -v D:/SoftTools/docker/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 ,这个先别用
// 1.进入主库容器
docker exec -it mysql-master bash
// 2.登录mysql
mysql -uroot -proot
// 3.rep表示复制账号;可修改为%,代表任意的主机;`IDENTIFIED BY`后面代表rep用户的认证密码
CREATE USER 'rep'@'<salve_ip>' IDENTIFIED WITH mysql_native_password BY 'reppassword';
GRANT REPLICATION SLAVE ON *.* TO 'rep'@'<salve_ip>';
// 1.进入主库容器
docker exec -it mysql-master bash
// 2.登录mysql
mysql -uroot -proot
// 3.rep表示复制账号;可修改为%,代表任意的主机;`IDENTIFIED BY`后面代表rep用户的认证密码
CREATE USER 'rep'@'%' IDENTIFIED WITH mysql_native_password BY 'rep';
GRANT REPLICATION SLAVE ON *.* TO 'rep'@'%';
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)
// 1.进入从库容器
docker exec -it mysql-slave bash
// 2.登录mysql
mysql -uroot -proot
不要直接复制,先看6.1
// 3.配置主库认证信息,和同上
CHANGE MASTER TO MASTER_HOST='' ,MASTER_PORT=10000,MASTER_USER='rep',MASTER_PASSWORD='reppassword',MASTER_LOG_FILE='' ,MASTER_LOG_POS=<Position>;
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;
在 slave 上启动线程:start slave;
查看状态
在 slave 上执行命令:show slave status\G;
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
如果没有成功,stop slave;
重新设置
设置从库只读: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后,再将以上流程重新跑了一遍,问题没有复现。在主库 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)
在从库操作:发现数据添加上了
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)
这个时候查看从库同步状态,发现报错了,怎么办,怎么办?请看下面
在刚才的情况下我们已经设置了从库只读,但是还要向从库中添加数据,就会导致从库同步状态报错,如下:
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
手动的解决方法是告诉从库slave_sql线程让他忽略掉这个错误继续执行:
set global sql_slave_skip_counter=1;
start slave;
上面的语句是告诉slave跳过当前卡住的event,然后重新起来干活。
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条数据为例
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;
## 发现从库还是正常运行的
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;
## 发现从库 已经挂了
主库不理会从库,继续添加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)
先把主库锁定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;
。因为如果主从数据差距太大,从库恢复起来要很长时间,
通过本地去连接远程的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;
之后可以成功连接。
参考连接:mybatisPlus3.x几行代码实现读写分离