实现目标
搭建两台MySQL服务器(一主一从),一台作为主服务器,一台作为从服务器,主服务器进行写操作,从服务器进行读操作。
工作流程概述
- 主服务器:
- 开启二进制日志
- 配置唯一的server-id
- 获得master二进制日志文件名及位置
- 创建一个用于slave和master通信的用户账号
- 从服务器:
- 配置唯一的server-id
- 使用master分配的用户账号读取master二进制日志
- 启用slave服务
准备工作
- 主从数据库版本最好一样
- 主从数据库内数据保持一致
- 主数据库:192.168.244.201 : 3306
- 从数据库:192.168.244.202 : 3306
开始配置
- 配置 Master 主服务器
- 找到主数据库的配置文件my.cnf(Windows中是my.ini),我的在/etc/my.cnf
在[mysqld]部分插入如下两行:
[mysqld]
log-bin=mysql-bin #开启二进制日志
server-id=201 #设置server-id,唯一值,标识主机
- 重启mysql服务
systemctl restart mysqld
- 创建用于主从同步的账号/密码
进入MySQL :mysql -u root -p
回车输入密码。
我创建的用户名叫“master_root”密码是“MySql@6688”
【注意:由于之前把密码改成支持简单密码123456的了,导致这里新建用户出现一些问题,说密码不符合策略等,后来干脆我重装mysql,使用默认复杂密码了,就没有这么多问题了。习惯就好其实。】
下面我都用的%,没有写具体ip,你可以自行决定。
#创建用户(IP为可访问该master的IP,任意IP就写'%')
mysql> CREATE USER 'master_root'@'192.168.244.202' IDENTIFIED BY 'MySql@6688';
#分配权限(IP为可访问该 master的IP,任意IP就写'%')
mysql> GRANT REPLICATION SLAVE ON *.* TO 'master_root'@'192.168.244.202';
#刷新权限
mysql>flush privileges;
- 查看master状态,记录二进制文件名(mysql-bin.000001)和位置(154).后面配从库要用。
show master status;
- 配置 Slave 主服务器
- 修改my.cnf 文件。
vim /etc/my.cnf
[mysqld]
server-id=202 #设置server-id,唯一值,唯一标识从库
- 重启mysql服务
systemctl restart mysqld
- 登录进入mysql,执行同步sql语句(主服务器名,用于主从的用户名,密码,二进制文件名,位置)
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.244.201',
-> MASTER_USER='master_root',
-> MASTER_PASSWORD='MySql@6688',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=154;
- 启动slave同步进程
mysql>start slave;
- 查看slave状态
show slave status\G
注意后面不要分号;否则最后一行显示报错如下:ERROR: No query specified
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.244.201
Master_User: master_root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: localhost-relay-bin.000007
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000002
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: 154
Relay_Log_Space: 531
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: 201
Master_UUID: 7dd766bb-f005-11e9-81ba-000c29a69f1b
Master_Info_File: /var/lib/mysql/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:
1 row in set (0.01 sec)
我也不知道为啥我这里这么长一段,网上的教程都是好短一段。管他呢,反正到这也对了。
当Slave_IO_Running和Slave_SQL_Running都为YES的时候就表示主从同步设置成功了。
特别注意:
- 可能遇坑:Slave_IO_Running :no ,并不是yes,为什么呢??
打开mysql的错误日志,不出意外在最后几行(看时间最新的记录),最后有这么一行:2019-10-16T12:59:09.987976Z 1 [ERROR] Slave I/O for channel '': Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. Error_code: 1593
意思master和slave的UUID相同了,应该不同才对的【如果你也是克隆的主机生成从机,就会出现这个问题】
解决办法:去mysql的data目录中,找到auto.cnf文件(不知道data目录的去my.cnf文件中看‘datadir=/var/lib/mysql’),然后删除该文件,接着重启mysql服务,就会自动重新生成一个新的auto.cnf文件(注意,此时操作的都是slaver,不是master。)
接下来就可以进行一些验证了,比如在主master数据库的test数据库的一张表中插入一条数据,在slave的test库的相同数据表中查看是否有新增的数据即可验证主从复制功能是否有效,还可以关闭slave(mysql>stop slave;),然后再修改master,看slave是否也相应修改(停止slave后,master的修改不会同步到slave),就可以完成主从复制功能的验证了。
还可以用到的其他相关参数:
master开启二进制日志后默认记录所有库所有表的操作,可以通过配置来指定只记录指定的数据库甚至指定的表的操作,具体在mysql配置文件的[mysqld]可添加修改如下选项:
不同步哪些数据库
binlog-ignore-db = mysql
binlog-ignore-db = test
binlog-ignore-db = information_schema
只同步哪些数据库,除此之外,其他不同步
binlog-do-db = game
如之前查看master状态时就可以看到只记录了test库,忽略了manual和mysql库。