主从复制原理

 
 
 
 
 
 
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           ---->只能控制普通用户(对管理员用户无效)
12-14 23:31