主从复制原理
主从复制的前提
1)两台或两台以上的数据库实例
2)主库要开启二进制日志
3)主库要有复制用户
4)主库的server_id和从库不同
5)从库需要在开启复制功能前,要获取到主库之前的数据(主库备份,并且记录binlog当时位置)
6)从库在第一次开启主从复制时,时必须获知主库:ip,port,user,password,logfile,pos
------
IP:10.0.0.51
Port:3306
User:rep
Password:oldboy123
logFile:mysql-bin.000002
Pos:120
------
7)从库要开启相关线程:IO、SQL
8)从库需要记录复制相关用户信息,还应该记录到上次已经从主库请求到哪个二进制日志
9)从库请求过来的binlog,首先要存下来,并且执行binlog,执行过的信息保存下来
主从复制涉及到的文件和线程
主库:
1)主库binlog:记录主库发生过的修改事件
2)dump thread:给从库传送(TP)二进制日志线程
从库:
1)relay-log(中继日志,差异日志):存储所有主库TP过来的binlog事件
**<font color='red'>relay-log会定期清除,在一个SQL线程执行完成之后,并且长时间不用的情况下</font>**
2)relay-log.info:记录relaylog的名字,和上一次读取relaylog的位置点
3)master.info:存储复制用户信息,上次请求到的主库binlog位置点
4)IO thread:接收主库发来的binlog日志,也是从库请求主库的线程
5)SQL thread:执行主库TP过来的日志
**做主从复制,是为了缓解主库的压力,并不是为了备份。(延时从库)**
原理
![](https://img.haomeiwen.com/i19559641/0ee1ef3e562a7c46.png)
1)通过change master to语句告诉从库主库的ip,port,user,password,file,pos
2)从库通过start slave命令开启复制必要的IO线程和SQL线程
3)从库通过IO线程拿着change master to用户密码相关信息,连接主库,验证合法性
4)从库连接成功后,会根据binlog的pos问主库,有没有比这个更新的
5)主库接收到从库请求后,比较一下binlog信息,如果有就将最新数据通过dump线程给从库IO线程
6)从库通过IO线程接收到主库发来的binlog事件,存储到TCP/IP缓存中,并返回ACK更新master.info
7)将TCP/IP缓存中的内容存到relay-log中
8)SQL线程读取relay-log.info,读取到上次已经执行过的relay-log位置点,继续执行后续的relay-log日志,执行完成后,更新relay-log.info
主从复制实践(生产实践)
主库有数据,并且一直在提供服务,不停库的情况下,添加新的从库
#1.还原环境
[root@db02 ~]# /etc/init.d/mysqld stop
[root@db02 ~]# rm -fr /application/mysql/data/
[root@db02 ~]# cd /application/mysql/scripts/
[root@db02 scripts]# ./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data
[root@db02 scripts]# /etc/init.d/mysqld start
------
[root@db03 ~]# /etc/init.d/mysqld stop
[root@db03 ~]# rm -fr /application/mysql/data/
[root@db03 ~]# cd /application/mysql/scripts/
[root@db03 scripts]# ./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data
[root@db03 scripts]# /etc/init.d/mysqld start
2.修改主库的配置
[root@db01 ~]# vim /etc/my.cnf
log-bin=mysql-bin
binlog_format=row
server_id=10
3.修改从库的配置
[root@db02 ~]# vim /etc/my.cnf
server_id=5
[root@db02 ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
------
[root@db03 ~]# vim /etc/my.cnf
server_id=5
[root@db03 ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
4.主库操作
#创建主从复制用户
mysql> grant replication slave on *.* to slave@'%' identified by '123';
#查看binlog位置点?(新主从环境)
mysql> show master status;
+------------------+----------+
| File | Position |
+------------------+----------+
| mysql-bin.000001 | 134 |
+------------------+----------+
#有数据的情况,打点全备
[root@db01 ~]# mysqldump -A -R --triggers --master-data=1 --single-transaction |gzip > /tmp/replication.sql.gz
#将打点全备的数据,发送到从库上
[root@db01 ~]# scp /tmp/replication.sql.gz 172.16.1.52:/tmp
[root@db01 ~]# scp /tmp/replication.sql.gz 172.16.1.53:/tmp
#导入数据
[root@db02 ~]# zcat /tmp/replication.sql.gz |mysql
[root@db03 ~]# zcat /tmp/replication.sql.gz |mysql
#如果全备数据很大,建议不要scp
[root@db01 ~]# zcat /tmp/replication.sql.gz |mysql -uroot -p123 -h10.0.0.52
[root@db01 ~]# zcat /tmp/replication.sql.gz |mysql -uroot -p123 -h10.0.0.53
5.从库操作
#找位置点和名字
[root@db02 ~]# zcat /tmp/replication.sql.gz |head -22|tail -1
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=161362;
#执行同步主库
change master to
master_user='slave',
master_password='123',
master_host='10.0.0.51',
master_log_file='mysql-bin.000002',
master_log_pos=161362;
#开启IO和SQL线程
start slave;
#检查主从复制状态
show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
### MySQL主从复制问题
**IO**
1.网络
ping 10.0.0.51
2.端口
telnet 10.0.0.51 3306
tcping 10.0.0.51 3306
3.用户名
4.密码
mysql -uslave -p123 -h10.0.0.51
![](https://img.haomeiwen.com/i19559641/d78fcd15904c2068.png)
5.反向解析
![](https://img.haomeiwen.com/i19559641/8d39e7df08733932.png)
vim /etc/my.cnf
[mysqld]
skip_name_resolve
#不正经
skip-name-resolv
skip-name-resolve
skip_name_resolv
6.binlog的名字和位置点一定要一致
![](https://img.haomeiwen.com/i19559641/d71fce9fcf987fa3.png)
mysql> show master status;
+------------------+----------+
| File | Position |
+------------------+----------+
| mysql-bin.000002 | 3149338 |
+------------------+----------+
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to
-> master_log_file='mysql-bin.000002',
-> master_log_pos=3149338;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
7.server_id相同
![](https://img.haomeiwen.com/i19559641/24e509ee5d287c5b.png)
mysql> show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id | 10 |
+---------------+-------+
[root@db03 ~]# vim /etc/my.cnf
server_id=5
8.UUID相同
![](https://img.haomeiwen.com/i19559641/a60a4260f710884f.png)
1.修改uuid
[root@db03 data]# vim auto.cnf [auto] server-uuid=54c76db8-20eb-11ea-bed9-000c29e98744
[root@db03 data]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
2.删除uuid
[root@db03 data]# rm -fr /application/mysql/data/auto.cnf
[root@db03 data]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
SQL
1.主库和从库数据不一致:
主库上有从库没有的数据
![](https://img.haomeiwen.com/i19559641/6a113701b3b77d6d.png)
[root@db03 data]# vim /etc/my.cnf slave-skip-errors=1032,1062,1007,1049
[root@db03 data]# /etc/init.d/mysqld restart
2.主库上没有从库上有的数据
![](https://img.haomeiwen.com/i19559641/49cd722778c0b2b1.png)
set global sql_slave_skip_counter=1;
mysql> stop slave; Query OK, 0 rows affected (0.00 sec)
mysql> set global sql_slave_skip_counter=1;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
但是以上操作都是有风险存在的
做主从复制之前,保证主库和从库的数据一致性。
3.1)重新备份数据库,恢复到从库 2)给从库设置为只读
#在命令行临时设置
set global read_only=1;
#在配置文件中永久生效
read_only=1
网友评论