主从复制原理
1、主从复制的前提
1.1 两台以上mysql实例
多台物理机
多个mysql实例
1.2 主库要开启二进制日志
1.3 主库要提供复制相关的用户
replication slave,一个比较特殊的权限
grant replication slave on *.* to repl@'10.0.0.%' identified by '123456';
1.4 从库需要将和主库相差的数据,进行追加
一般情况是手动备份主库数据,恢复到从库上
1.5 从库恢复到主库备份的时间点,开始自动从主库获取新的二进制日志开始应用
因此需要人为告诉从库,从哪开始自动开始复制二进制日志(file+position),另外还需要告诉从库user,passwd,port,ip
mysql>CHANGE MASTER TO
MASTER_HOST='主库的ip地址',
MASTER_USER='replication的用户名',
MASTER_PASSWORD='replication用户名的密码',
MASTER_PORT=3306,端口号
MASTER_LOG_FILE='master2-bin.001',binlog日志
MASTER_LOG_POS=4, position号
MASTER_CONNECT_RETRY=10; 连接次数
-------------------
2、复制中的线程及文件
2.1、主库
Dump(IO) thread:在复制过程中,主库发送二进制日志的线程
2.2、从库
IO thread:向主库请求二进制日志,并且接受二进制日志的线程
SQL thread:执行请求过来的二进制的线程
2.3、主库
binlog文件:主库的二进制日志
2.4、从库
relaylog:中继日志,存储请求过来的二进制日志
master.info:
1、从库连接主库的重要参数(user,passwd,ip,port)
2、上次获取过的主库二进制日志的位置
relay-log.info
存储从库SQL线程已经执行过的relaylog日志位置
------------------
主从复制的工作原理
1 从库,IO线程,读取master.info中的信息,
获取到连接参数(user\passwd\ip\port)+上次请求过的主库的binlog的位置(例子:mysql-bin.000003,position=640)
2 IO线程使用链接到主库,拿着位置信息(mysql-bin.000003,position=640),问主库有没有比这个更新的二进制日志。
3 主库查询二进制日志,并对比从库发送过来的位置信息(mysql-bin.000003,position=640),如果有新的二进制日志,会通过
dump thread发送给从库。
4 从库通过IO线程,接受主库发来的二进制日志,存储到TCP/IP缓存中,并且返回“ACK”确认给主库,这时主库收到ACK后,
就认为复制完成了,可以继续其他工作了。
5 从库更新master.info,二进制日志位置更新为新的位置信息。
6 从库IO线程会将TCP/IP缓存中的日志,存储到relay-log中继日志文件中。
7 从库SQL线程,读取relay-log.info,获取到上次执行到的relaylog日志位置,以这个位置信息作为起点,往后继续执行中继日志。
8 SQL线程执行完成所有relaylog之后,会更新relay-log.info信息为新位置信息。
到此为止,一次完整的复制过程就完成了。
mysql的1主1从的配置
master :mysql1 10.0.0.101
slave1 :mysql2 10.0.0.102
1、mysql 安装省略
2、配置msyql的my.cnf文件
master:mysql1配置文件
[client]
user = root
password = 123456
socket = /tmp/socket
port = 3306
[mysqld]
basedir = /application/mysql
datadir = /application/mysql/data
port = 3306
server_id = 101
socket = /tmp/socket
log-error = /application/mysql/logs/mysql1.err
pid_file = /application/mysql/data
log_bin = /application/mysql/binlogs/mysql1-bin
binlog_format = row
skip-name-resolve
slave1:mysql2的配置文件
[client]
user = root
password = 123456
socket = /tmp/socket
port = 3306
[mysqld]
basedir = /application/mysql
datadir = /application/mysql/data
port = 3306
server_id = 102
socket = /tmp/socket
log-error = /application/mysql/logs/mysql2.err
pid_file = /application/mysql/data
log_bin = /application/mysql/binlogs/mysql2-bin
binlog_format = row
skip-name-resolve
启动mysql
[root@mysql-1 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
[root@mysql-2 ~]# /etc/init.d/mysqld start
Starting MySQL...... SUCCESS!
在master:10.0.0.101的数据库上配置replication slave的用户名和密码
mysql> grant replication slave on *.* to repl@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.10 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
在master:10.0.0.101上查看log_file和log_pos信息
show master status\G;
mysql> show master status\G
*************************** 1. row ***************************
File: mysql1-bin.000001
Position: 191
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)
在slave1:10.0.0.102的从库上配置主库相应的信息,并开启从库
mysql> CHANGE MASTER TO
MASTER_HOST='10.0.0.101',
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql1-bin.000001',
MASTER_LOG_POS=191;
Query OK, 0 rows affected, 2 warnings (0.20 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
查看从库slave1:10.0.0.102的从库信息 mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.101 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql1-bin.000001 Read_Master_Log_Pos: 120 Relay_Log_File: mysql-2-relay-bin.000003 Relay_Log_Pos: 284 Relay_Master_Log_File: mysql1-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes 主从关系已经建立完成
测试在master:10.0.0.101上创建king的数据库,在查看slave1:10.0.0.102数据库是否同步 master:10.0.0.101 mysql> create database king; Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | king | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) slave1:10.0.0.102 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | king | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.01 sec) 主从同步完成
一些故障说明: IO线程故障: 1、主库连接不上 user、password、port、ip 错误 解决方案: stop slave; reset slave all; change master to start slave; 防火墙 网络不通 skip-name-resolve stop slave; start slave; 2、主库二进制日志丢失或损坏 解决方案: stop slave; reset slave all; 重新备份恢复 change master to start slave; SQL线程故障: 执行relaylog日志新事件 1、删除、修改对象的操作时,没有这个对象 2、创建对象时,对象已存在 3、主键冲突 从库做写入操作,会导致以上问题出现 处理方法: stop slave; set global sql_slave_skip_counter = 1; start slave; /etc/my.cnf slave-skip-errors = 1032,1062,1007 但是,以上操作有时是有风险的,最安全的做法就是重新构建主从。 怎么预防以上问题? 从库加入配置文件 mysql>set global read_only=1; vim /etc/my.cnf read_only=1 ---->只能控制普通用户(对管理员用户无效)