MySQL主从复制

一、概念

MySQL主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。

MySQL数据库的主从复制方案,是其自带的功能,MySQL数据库支持单向、双向、链式级联,等不同业务场景的复制。

一台MySQL服务器一旦启用二进制日志后,其作为主服务器(Master),它的数据库中所有操作都会以"事件"的方式记录在二进制日志中,其他数据库作为从服务器(Slave)通过一个I/O线程与主服务器保持通信,并监控Master的二进制日志文件的变化,如果发现Master二进制日志文件发生变化,则会把变化复制到自己的中继日志中,然后Slave的一个SQL线程会把相关的"事件"执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了主从复制。

在生产环境中,MySQL主从复制都是异步的复制方式,即不是严格的实时复制,但是给用户的体验都是实时的。MySQL主从复制集群功能使得MySQL数据库支持大规模高并发读写成为可能,且有效的保护了服务器宕机的数据备份。

主从复制的逻辑有以下几种:

一主一从:单向主从同步模式,只能在Master端写入数据。

一主多从:提高系统的读性能。

双主复制:此架构可以在Master1或Master2进行数据写入,或者两端同时写入(特殊设置)。

多主一从(MySQL5.7开始支持)

级联复制

应用场景:

利用复制功能,当Master服务器出现问题时,我们可以人工的切换到从服务器继续提供服务,此时服务器的数据和宕机时的数据几乎完全一致。

复制功能也可用作数据备份,但是如果人为的执行drop,delete等语句删除,那么从库的备份功能也就失效了。

主从机制实现原理:

MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread、SQL thread)运行在从节点,如下图所示:

主库 binary log dump 线程:

当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送binlog内容到从库。对于每一个即将发送给从库的sql事件,此线程会将其锁住。一旦该事件被线程读取完之后,该锁会被释放,即使在该事件完全发送到从库之前,该锁也会被释放。

从库 I/O 线程:

当从节点执行"start slave"命令之后,从节点会创建一个I/O线程用来连接主节点,请求主节点发送binlog里面的更新记录到从节点上。I/O线程接收到主节点binlog dump线程发来的更新之后,保存在本地relay log中。

从库SQL线程:

SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。

对于每一个主从连接,都需要三个线程来完成。当主节点有多个从节点时,主节点会为每一个当前连接的从节点建一个binary log dump 线程,而每个从节点都有自己的I/O线程,SQL线程。从节点用两个线程将从主库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。比如,如果从节点没有运行,此时I/O进程可以很快从主节点获取更新,尽管SQL线程还没有执行。如果在SQL线程执行之前从节点服务停止,至少I/O线程已经从主节点拉取到了最新的变更并且保存在本地relay log中,当服务再次起来之后,就可以完成数据的同步。

二、配置

master主库配置

# 查看数据库状态
service mysqld status

# 停止运行mysql
service mysqld stop

# 修改配置文件
vim /etc/my.cnf
# 修改内容
# 解释:server-id服务的唯一标识(主从之间都必须不同);log-bin启动二进制日志名称为mysql-bin
[mysqld]
server-id=1
log-bin=mysql-bin

# 重新启动mysql
service mysqld start

master主库添加从库账号

# 1、新建用于主从同步的用户pd,允许登录的从库是"10.0.0.0"
mysql> create user "pd"@"192.168.1.105" identified by "123456";

# 2、如果提示密码太简单不复合策略加在前面加这句
mysql> set global validate_password_policy=0;
# 给从库账号授权,说明给pd从库复制的权限,在"10.0.0.0"机器上复制
mysql> grant replication slave on *.* to "pd"@"192.168.1.105";

# 3、检查主库创建的复制账号
mysql> select user,host from mysql.user;
# 检查授权账号的权限
mysql> show grants for "pd"@"192.168.1.105";
# 实现对主数据库锁表只读,防止数据写入,数据复制失败
mysql> flush table with read lock;

# 4、检查主库的状态
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
# File是二进制日志文件名,Position是日志开始的位置。后面从库会用到!!!

# 5、锁表后,一定要单独再打开一个ssh窗口,导出数据库的所有数据
mysqldump -uroot -p --all-databases > /all.sql

# 6、确保数据导出后,没有数据插入,完毕再查看主库状态
mysql> show master status;

# 7、导出数据完毕后,解锁主库,恢复可写
mysql> unlock tables;

# 8、将备份导出的数据sql至Slave数据库
scp /all.sql root@192.168.1.105:/all.sql

slave从库配置

# 1、设置server-id值并关闭binlog功能参数
# 数据库的server-id在主从复制体系内是唯一的,slave的server-id与主库以及其他从库不同,并且注释掉slave的binlog参数

# 2、修改slave的配置:vim /etc/my.cnf
[mysqld]
server-id=2

# 3、重启数据库
service mysqld restart

# 4、检查slava从数据库的各项参数
mysql> show variables like "log_bin";
mysql> show variables like "server_id";

# 5、将master库的数据导入到slave库(注意sql文件的路径)
方法一:
mysql>source /all.sql;
方法二:
mysql -uroot -p < all.sql

# 6、配置复制的参数,slave从库连接master主库的配置
mysql> change master to master_host="192.168.1.106",
       master_user="pd",
       master_password="123456",
       master_log_file="mysql-bin.000002",
       master_log_pos=154;

# 7.启动从库的同步开关,测试主从复制的情况
mysql> start slave;

# 8、查看复制状态
mysql> show slave status\G

检查主从复制是否成功,如下所示即为成功:

注意:

此时还未配置从库的只读模式,只需在slave服务器上配置/etc/my.cnf,加入read-only=true,并且在slave上创建普通用户,使用普通用户主从同步即可达到只读的效果;如果用root用户,无法达到readonly!!!

[mysqld]
read-only=true

 

posted @ 2019-03-25 19:13  就俗人一个  阅读(578)  评论(0编辑  收藏  举报