1.MySQL主从复制原理
MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL thread)运行在从节点,如下图所示:
主节点 binary log dump 线程
当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。
从节点I/O线程
当从节点上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log(中继日志)中。
从节点SQL线程
SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。
要实施复制,首先必须打开Master 端的binary log(bin-log)功能,否则无法实现。因为整个复制过程实际上就是Slave 从Master 端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。如下图所示:
复制的基本过程如下:
(1) 从节点上的I/O 进程连接主节点,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
(2)主节点接收到来自从节点的I/O请求后,通过负责复制的I/O进程根据请求信息读取指定日志指定位置之后的日志信息,返回给从节点。返回信息中除了日志所包含的信息之外,还包括本次返回的信息的bin-log file 的以及bin-log position;
(3)从节点的I/O进程接收到内容后,将接收到的日志内容更新到本机的relay log中,并将读取到的binary log文件名和位置保存到master-info 文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log 的哪个位置开始往后的日志内容,请发给我”;
(4)Slave 的 SQL线程检测到relay-log 中新增加了内容后,会将relay-log的内容解析成在祝节点上实际执行过的操作,并在本数据库中执行。
2.Mysql的主从异步复制(Asynchronous replication)
(1)异步的解释:
1、逻辑上
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
2、技术上
主库将事务 Binlog 事件写入到 Binlog 文件中,此时主库只会通知一下 Dump 线程发送这些新的 Binlog,然后主库就会继续处理提交操作,而此时不会保证这些 Binlog 传到任何一个从库节点上。
(2)异步复制的实现:
所需环境:主库:172.25.33.1 server1
从库:172.25.33.2 server2
主库的操作如下:
<1>下载所需安装包并解包:
[root@server1 ~]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@server1 ~]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@server1 ~]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-devel-5.7.24-1.el7.x86_64.rpm
mysql-community-embedded-5.7.24-1.el7.x86_64.rpm
mysql-community-embedded-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-embedded-devel-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-minimal-debuginfo-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm
mysql-community-server-minimal-5.7.24-1.el7.x86_64.rpm
mysql-community-test-5.7.24-1.el7.x86_64.rpm
<2>删除不需要的rpm包并安装剩余的rpm包:
[root@server1 ~]# rm -fr mysql-community-devel-5.7.24-1.el7.x86_64.rpm
[root@server1 ~]# rm -fr mysql-community-embedded-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-compat-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-devel-5.7.24-1.el7.x86_64.rpm mysql-community-minimal-debuginfo-5.7.24-1.el7.x86_64.rpm mysql-community-server-minimal-5.7.24-1.el7.x86_64.rpm mysql-community-test-5.7.24-1.el7.x86_64.rpm
[root@server1 ~]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm
[root@server1 ~]# yum install -y *.rpm
<3>修改配置文件,启动数据库,并获得生成的初始密码:
[root@server1 ~]# vim /etc/my.cnf
29 log-bin=mysql-bin
30 server-id=1
[root@server1 ~]# systemctl start mysqld
[root@server1 ~]# cat /var/log/mysqld.log | grep password
<4>数据库安全初始化,并使用新密码登陆:
mysql_secure_installation
mysql -uroot -p #登陆成功!
<5>创建用来主从复制的用户repl,查看主节点状态:
mysql> CREATE USER 'repl'@'172.25.33.%' IDENTIFIED BY 'Liuyan&123';
Query OK, 0 rows affected (0.04 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.25.33.%';
Query OK, 0 rows affected (0.29 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.04 sec)
mysql> show plugins; #查看限制密码插件#######
mysql> show master status; ##查看节点状态
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 1323 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
<6>真机测试,repl用户能否登陆:
[root@foundation72 ~]# mysql -h 172.25.33.1 -urepl -p
从库的操作如下:
<1>执行主库操作的1-4步,区别的是配置文件的修改:
##下载所需安装rpm包#####
scp [email protected]:/root/*.rpm .
yum install -y *
##修改配置文件#######
[root@server2 ~]# vim /etc/my.cnf
server-id=2
systemctl start mysqld
##查看密码并安全初始化#####
cat /var/log/mysqld.log | grep password
mysql_secure_installation
<2>登陆数据库设置,并开启从节点:
mysql -uroot -p
mysql> CHANGE MASTER TO
-> MASTER_HOST='172.25.33.1', #主节点ip
-> MASTER_USER='repl',
-> MASTER_PASSWORD='Liuyan&123',
-> MASTER_LOG_FILE='mysql-bin.000002', #所读数据目录
-> MASTER_LOG_POS=1323; #所读数据位置 同步数据的起始位置
mysql> start slave;
Query OK, 0 rows affected (0.08 sec)
mysql> show slave status\G #查看从节点状态,
Slave_IO_Running: Yes #这两行必须是yes,否则有问题
Slave_SQL_Running: Yes
这样,主从异步复制就已经实现了,进行测试
主节点的操作:
mysql -uroot -p
mysql> create database westos; #创建westos库;
mysql> use westos; #使用westos;
mysql> create table usertb ( #建表
-> username varchar(10) not null,
-> password varchar(20) not null);
mysql> desc usertb; #查看表结构
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | | NULL | |
| password | varchar(20) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
mysql> insert into usertb values ('user1','123');
Query OK, 1 row affected (0.09 sec)
mysql> select * from usertb; #查看表中所有内容
+----------+----------+
| username | password |
+----------+----------+
| user1 | 123 |
+----------+----------+
1 row in set (0.00 sec)
从节点的操作:
mysql -uroot -p
mysql> show databases; #可以看到westos库
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| westos |
+--------------------+
5 rows in set (0.00 sec)
mysql> use westos;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from usertb; #可以看到表中所有内容
+----------+----------+
| username | password |
+----------+----------+
| user1 | 123 |
+----------+----------+
1 row in set (0.00 sec)
mysql> exit