MySQL主从复制
一、MySQL主从复制基础概念
1.什么是mysql的主从复制?
MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。
MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。
# 异步复制技术是指,当用户请求更新数据时,主数据库处理完请求后可直接给用户响应,而不必等待备数据库完成同步,即备数据库会异步进行数据的同步,用户的更新操作不会因为备数据库未完成数据同步而导致阻塞。
(个人理解:从数据库不需要一直索要数据,主库完成更新后自动发送数据到从库中)
2.为什么需要主从复制 ?
1)在一个业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。 # 维持系统稳定性
2)做数据的热备 # 防止数据丢失
3)架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。 # 类似于连锁店。
3.主从复制原理
(1)master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时,则将其改变写入二进制日志中;
(2)slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O Thread (线程) 请求 master二进制事件(event);
(3)同时主节点为每个I/O线程启动一个dump线程(相当于专用路径),用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。
# 类似于手机更新(手机新版本会先通过专用的路径(dump线程)下载更新包,这个事件会通知到手机的通知栏中(中继日志),当机主发现后会点击进去,启用安装程序(SQL线程)准备安装。当版本同步后,安装程序休眠)
也就是说:
从库会生成两个线程,一个I/O线程,一个SQL线程;
主库会生成一个log dump线程,用来给从库I/O线程传binlog;
I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;
SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;
4.MySQL复制常用的拓扑结构
主从类型(Master-Slave)
主主类型(Master-Master)
级联类型(Master-Slave-Slave)
5.主从复制实现步骤:
1、从库通过手工执行change master to 语句连接主库,提供了连接的用户一切条件(user 、password、port、ip),并且让从库知道,二进制日志的起点位置(file名 position 号); startslave
2、从库的IO线程和主库的dump线程建立连接。
3、从库根据change master to 语句提供的file名和position号,IO线程向主库发起binlog的请求。
4、主库dump线程根据从库的请求,将本地binlog以events的方式发给从库IO线程。
5、从库IO线程接收binlog events,并存放到本地relay-log中,传送过来的信息,会记录到 master.info中
6、从库SQL线程应用relay-log,并且把应用过的记录到relay-log.info中,默认情况下,已经应用过的 relay 会自动被清理purge
二、实现MySQL主从复制
环境:
主库:
镜像:centos-7
IP:192.168.11.128
从库:
镜像:centos-7
IP:192.168.11.129
# 安装mysql
# 修改mysql密码(5.7.18)
update user set authentication_string=password('#123456@') where user='root';
# 关闭密码安全
validate_password=off
主库:
1)设置server-id值并开启binlog参数
vim /etc/my.cnf
[mysqld]
log_bin = mysql-bin
server_id = 128
# 重启数据库
systemctl restart mysqld
2)准备数据
mysql -uroot -p123456
create database school;
use school
1.创建student和score表
CREATE TABLE student (
id INT(10) NOT NULL UNIQUE PRIMARY KEY ,
name VARCHAR(20) NOT NULL ,
sex VARCHAR(4) ,
birth YEAR,
department VARCHAR(20) ,
address VARCHAR(50)
);
创建score表。SQL代码如下:
CREATE TABLE score (
id INT(10) NOT NULL UNIQUE PRIMARY KEY AUTO_INCREMENT ,
stu_id INT(10) NOT NULL ,
c_name VARCHAR(20) ,
grade INT(10)
);
2.为student表和score表增加记录
向student表插入记录的INSERT语句如下:
INSERT INTO student VALUES( 901,'张老大', '男',1985,'计算机系', '北京市海淀区');
INSERT INTO student VALUES( 902,'张老二', '男',1986,'中文系', '北京市昌平区');
INSERT INTO student VALUES( 903,'张三', '女',1990,'中文系', '湖南省永州市');
INSERT INTO student VALUES( 904,'李四', '男',1990,'英语系', '辽宁省阜新市');
INSERT INTO student VALUES( 905,'王五', '女',1991,'英语系', '福建省厦门市');
INSERT INTO student VALUES( 906,'王六', '男',1988,'计算机系', '湖南省衡阳市');
向score表插入记录的INSERT语句如下:
INSERT INTO score VALUES(NULL,901, '计算机',98);
INSERT INTO score VALUES(NULL,901, '英语', 80);
INSERT INTO score VALUES(NULL,902, '计算机',65);
INSERT INTO score VALUES(NULL,902, '中文',88);
INSERT INTO score VALUES(NULL,903, '中文',95);
INSERT INTO score VALUES(NULL,904, '计算机',70);
INSERT INTO score VALUES(NULL,904, '英语',92);
INSERT INTO score VALUES(NULL,905, '英语',94);
INSERT INTO score VALUES(NULL,906, '计算机',90);
INSERT INTO score VALUES(NULL,906, '英语',85);
3)备份
mysqldump -uroot -p123456 -B school it > db.sql
mysqldump -uroot -p123456
grant replication slave on *.* to 'rep'@'192.168.11.%' identified by '123456';
show master status;
7) 主库备份数据上传到从库
# scp ./db.sql 192.168.11.129:/opt/
从库:
1)设置server-id并关闭binlog参数
vim /etc/my.cnf
#log_bin
server-id = 129
# 重启数据库
systemctl restart mysqld
2)同步数据
mysql -uroot -p123456 < /opt/db.sql
mysql -uroot -p123456 -e 'show databases'
mysql -uroot -p123456
source /opt/db.sql
3) 开启主从同步
change master to
-> master_host='192.168.11.128',
-> master_user='rep',
-> master_password='123456',
-> master_log_file='mysql-bin.000011',
-> master_log_pos=448;
4)启动从库同步开关
start slave;
# 检查状态:
show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
测试主从同步:
主库创建一个数据库:
# mysql -uroot -p123456 -e 'create database test_m_s;'
从库检查:
# mysql -uroot -p123456 -e 'show databases;' | grep "test_m_s"
# 完成同步