主从复制要求
MySQL 主从复制对主机和 MySQL 的要求
(1)主从服务器操作系统版本和位数必须一致;
(2)主节点(Master)和从节点(Slave)数据库版本必须一致;
(3)主节点(Master)和从节点(Slave)数据库中的数据必须一致;
(4)主节点(Master)需要开启二进制日志;
(5)主节点(Master)和从节点(Slave)的 server-id 在局域网内必须唯一。
主从配置
主从服务器信息
主服务器
- IP 192.168.0.15
- 数据库 syncdb
从服务器
- IP 192.168.0.16
- 数据库 syncdb
主节点-配置
- 安装数据库;
- 修改数据库配置文件,指定 server-id,开启二进制日志(log-bin);
- 启动数据库,查看当前是哪个日志,position 号是多少;
- 登录数据库,授权数据复制用户(IP 地址为从机 IP 地址);
- 备份数据库(记得加锁和解锁);
- 传送备份数据到 Slave;
- 启动数据库。
步骤
修改配置
1 | vi /etc/my.cnf |
增加以下配置项:
1 | [mysqld] |
说明:二进制日志(binlog)的复制类型
- 基于语句的复制(statement):在 Master 上执行的 SQL 语句,在 Slave 上执行同样的语句。
MySQL 默认采用基于语句的复制,效率比较高。一旦发现没法精确复制时,会自动选择基于行的复制。 - 基于行的复制(row):把改变的内容复制到 Slave,而不是把命令在 Slave 上执行一遍。从mySQL5.0 开始支持。
- 混合类型的复制(mixed):默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。
查看
1 | grep "binlog-ignore-db" /etc/my.cnf |
重启MySQL
1 | service mysqld restart |
创建同步用户
1 | set global validate_password_policy=0; |
锁表
1 | flush tables with read lock; |
查看状态
1 | show master status\G |
结果如图
记录下里面的File和Position的值,从节点同步时要用。
注意点
注意点1
主从节点的
server-id
要不一样。
注意点2
注意以下两个配置是互斥的,不能同时配置
1 | binlog-do-db = syncdb ## 复制过滤:需要备份的数据库,输出 binlog |
如果同时配置的话
如上示例,我这测试的效果是除了
mysql
库,其它的库都产生binlog了,也就是说binlog-ignore-db
生效了,而binlog-do-db
没生效。
注意点3
如果要设置同步多个库这么写,不能用逗号分割
1 | binlog-do-db = syncdb1 |
主节点-数据备份
备份 syncdb 数据库中的数据
1 | mysqldump -uroot -p --add-drop-table syncdb > /tmp/syncdb-bak.sql |
将主节点的 syncdb 备份传送到从节点
1 | scp -P 2222 /tmp/syncdb-bak.sql root@192.168.0.16:/tmp/ |
从节点-数据导入
1 | create database syncdb; |
从节点-配置
(1)安装数据库;
(2)修改数据库配置文件,指明 server-id;
(3)启动数据库,还原备份;
(4)指定 Master 的地址、用户、密码等信息;
(5)开启同步,查看状态。
修改配置
1 | vi /etc/my.cnf |
增加以下配置项:
1 | server-id = 102 ## server-id,一般设置为 IP 的最后一段 |
说明:
如果 Slave 为其它 Slave 的 Master 时,必须设置 bin_log;
relay_log 配置中继日志;
log_slave_updates 表示 slave 将复制事件写进自己的二进制日志。当设置 log_slave_updates 时,你可以让 slave 扮演其它 slave 的 master。
此时,slave 把 SQL 线程执行的事件写进行自己的二进制日志(binary log),然后,它的 slave 可以获取这些事件并执行它。
重启MySQL
1 | service mysqld restart |
从节点也可以有多级
先停止之前的
1 | stop slave; |
设置主从复制
1 | change master to master_host = '192.168.0.15',master_user = 'sync',master_password = 'psvmc123456',master_port = 13306,master_log_file = 'mysql01-bin.000001', master_log_pos = 720, master_connect_retry = 30; |
参数说明:
1 | master_host = '192.168.1.15' ## Master 的 IP 地址 |
查看主从同步状态:
1 | show slave status\G |
开启主从复制
1 | start slave; |
查看主从同步状态:
1 | show slave status\G |
主要看以下两个参数,这两个参数如果是 Yes 就表示主从同步正常:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
主节点-解锁表
开启同步后解锁主节点数据库表
1 | unlock tables; |
重置主从复制
如果遇到同步出错,可在 Slave 上重置主从复制设置,步骤如下:
重置主从复制设置
1 | stop slave; |
重新设置主从复制参数
1 | change master to master_host = '192.168.0.15',master_user = 'sync',master_password = 'psvmc123456',master_port = 13306,master_log_file = 'mysql01-bin.000001', master_log_pos = 720, master_connect_retry = 30; |
启动
1 | start slave; |
查看主从同步状态
1 | show slave status\G |
主从复制参数
主
binlog-do-db
主生成binlog的数据库binlog-ignore-db
主生成binlog忽略的数据库
从
replicate-do-db
从复制的数据库replicate-ignore-db
从复制忽略的数据库replicate-wild-do-table
从复制的表replicate-wild-ignore-table
从复制忽略的表
误区
这里说一个误区
binlog-do-db
、binlog-ignore-db
、replicate-do-db
、replicate-ignore-db
并不像你想的那样工作.
想象如下的场景:
你设置了 binlog-ignore-db = logdb
,
所以我们以为logdb数据库(在slave上不存在这个数据库) 中的数据不会被复制
但是当我们在主库中执行以下的操作
1 | mysql> delete from logdb.tuser; |
复制会broke2次,
第一次,主库会依旧会产生binlog,所以slave尝试着去执行你给第一条语句,但是slave上并没有这样的表logdb.tuser
第二次,因为use logdb;
所以syncdb
也不会产生binlog,所以对syncdb.users
不会被复制
为什么?
因为 binlog-ignore-db 并不像你想的那样执行, 我们认为的: 在logdb数据库中的数据不会被复制
是错的,
实际上(数据库)并没有这么做.事实上, 他是通过默认的数据库为logdb
的连接, 过滤二进制的(SQL)语句日志的.
换句话说:
过滤不是基于 查询的字符串的, 而实际于你used的数据库。
其他的配置选项也都类似.
安全的替换方案是 在 slave上配置过滤, 使用基于查询中真正涉及到的表的选项,
这些是:
1 | replicate-wild-do-table |
例如, 避免复制 logdb数据库中的数据的安全的方案是 配置:
1 | replicate-wild-ignore-table=logdb.% |
这样做仍然有一些特殊的情况, 不能正常工作,但可以在更多的情况下正常工作,并且会遇到更少的意外.
推荐配置
主库配置:
1 | binlog-ignore-db = mysql |
从库配置:
1 | replicate-wild-do-table = syncdb.% |