复制是指将主数据库的DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。
MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。
Mysql 中有一种日志叫做 bin 日志(二进制日志)。这个日志会记录下所有修改了数据库的SQL 语句(insert,update,delete,create/alter/drop table, grant 等等)。
主从复制的原理其实就是把主服务器上的 bin 日志复制到从服务器上执行一遍,这样从服务器上的数据就和主服务器上的数据相同了。
从上层来看,复制分成三步:
详细过程:
复制中线程的作用:
从节点:
I/O Thread: 从 Master 节点请求二进制日志事件,并保存于中继日志中。
Sql Thread: 从Relay log 中读取日志事件并在本地完成重放。
主节点:
思考:从节点需要建立二进制日志文件吗?
看情况,如果从节点需要作为其他节点的主节点时,是需要开启二进制日志文件的。这种情况叫做级联复制。如果只是作为从节点,则不需要创建二进制文件。
MySQL 复制的优点主要包含以下三个方面:
主节点:
启用二进制日志。
为当前节点设置一个全局唯一的server_id。
创建有复制权限的用户账号 REPLIACTION SLAVE ,REPLIATION CLIENT。
从节点:
启动中继日志。
为当前节点设置一个全局唯一的server_id。
使用有复制权限的用户账号连接至主节点,并启动复制线程。
注意前提:
- 防火墙是关闭的
- 我这里是两台电脑测试的,需要把VM虚拟机两台网络模式改为桥接模式,然后在Linux中测试是否可以ping通,如果双方互通网络是没毛病的
#mysql 服务ID,保证整个集群环境中唯一
server-id=1
#mysql binlog 日志的存储路径和文件名
log-bin=/var/lib/mysql/mysqlbin
# 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
# 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
# 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
#是否只读,1 代表只读, 0 代表读写
read-only=0
#忽略的数据, 指不需要同步的数据库(mysql库一般不同步)
binlog-ignore-db=mysql
#指定同步的数据库
#binlog-do-db=db01
service mysqld restart
创建同步数据的账户,并且进行授权操作:
在主库创建一个复制帐号,这个帐号是给从库的IO线程建立连接到主库时用的,从库会用这个帐号连接主库并读取主库的二进制日志:
grant replication slave on *.* to 'zhr123'@'192.168.107.49' identified by '123abc';
flush privileges;
账号:自定义
IP端口:指定子端口
密码:自定义(如果密码不成功,需要改一下策略)
解决办法:
查看master状态:
show master status;
字段含义:
File : 从哪个日志文件开始推送日志文件
Position : 从哪个位置开始推送日志
Binlog_Ignore_DB : 指定不需要同步的数据库
#mysql服务端ID,唯一
server-id=2
#指定binlog日志
log-bin=/var/lib/mysql/mysqlbin
read_only = 1
service mysqld restart;
change master to master_host= '主库IP', master_user='主库账号',
master_password='主库密码', master_log_file='mysqlbin.000001', master_log_pos=413;
指定当前从库对应的主库的IP地址,用户名,密码,从哪个日志文件开始的那个位置开始同步推送日志。
start slave;
show slave status\G
输出结果中应该看到 I/O 线程和 SQL 线程都是 YES
, 就表示成功。
执行此过程后,在主服务上操作的修改数据的操作都会在从服务器中执行一遍,这样就保证了数据的一致性。
stop slave;
create database db01;
use db01;
create table user(
id int(11) not null auto_increment,
name varchar(50) not null,
sex varchar(1),
primary key (id)
)engine=innodb default charset=utf8;
insert into user(id,name,sex) values(null,'Tom','1');
insert into user(id,name,sex) values(null,'Trigger','0');
insert into user(id,name,sex) values(null,'Dawn','1');
在从库中,可以查看到刚才创建的数据库:
在该数据库中,查询user表中的数据: