Linux
Nginx,MySQL,PHP/Python

MySQL主从复制基础

简介

1.基于二进制日志复制
2.主库的修改操作会记录二进制日志
3.从库会请求新的二进制日志并回放,最终达到主从数据同步
4.核心功能
  辅助备份,处理物理损坏
主从复制前提
1.两台以上mysql实例,server_id,server_uuid不同
2.主库开启二进制日志
3.专用的复制用户
4.保证主从开启之前的某个时间点,从库数据是和主库一致
5.告知从库,复制user,passwd,IP port,以及复制起点(change master to)
6.线程:Dump thread,IO thread,SQL thread开启,start slave

搭建

准备两个实例,准备配置文件
cat > /data/3307/my.cnf <<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
log_error=/data/3307/mysql.log
port=3307
server_id=7
log_bin=/data/3307/mysql-bin
EOF

初始化数据
[root@db01 ~]# mysqld --initialize-insecure  --user=mysql --datadir=/data/3307/data --basedir=/app/mysql

systemd管理多实例
[root@db01 ~]# cd /etc/systemd/system/
[root@db01 ~]# cd /etc/systemd/system/
[root@db01 system]# cp mysqld.service mysqld3307.service 
[root@db01 system]# vim mysqld3307.service ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
[root@db01 system]# sysctl -p

授权
[root@db01 system]# chown -R mysql.mysql /data/*

启动
[root@db01 system]# systemctl start mysqld3307.service

检查
[root@db01 ~]# netstat -lnp|grep 330
tcp6       0      0 :::3306                 :::*                    LISTEN      2107/mysqld         
tcp6       0      0 :::3307                 :::*                    LISTEN      2053/mysqld
这是一台机器开启两个mysql实例,我用的是两台机器,各一台mysql

两个实例db01,db02
db01 [(none)]>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
| world              |
+--------------------+
6 rows in set (0.00 sec)

db02 [(none)]>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)



主库中创建专用的复制用户
db01 [(none)]>grant replication slave on *.* to aaaa@'10.0.0.%' identtified by '123';
Query OK, 0 rows affected, 1 warning (0.00 sec)

把db01做主库,在db01做个全备
[root@db01 ~]# mysqldump -uroot -p -A -R -E --triggers --master-data=2  --single-transaction --set-gtid-purged=OFF >/test/full.sql 
Enter password: 
[root@db01 ~]# ll /test
total 1004
-rw-r--r-- 1 root root 1028005 Jun 28 18:40 full.sql

把全备恢复到db02从库中
[root@db01 ~]# scp /test/full.sql 10.0.0.52:/root
root@10.0.0.52's password: 
db02 [(none)]>source /root/full.sql
db02 [world]>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
| world              |
+--------------------+
6 rows in set (0.00 sec)

db02做master to
db02 [world]>change master to
    ->   MASTER_HOST='10.0.0.51',           主库的IP地址
    -> MASTER_USER='aaaa',                  专用复制用户
    ->   MASTER_PASSWORD='123',             复制用户密码
    ->  MASTER_PORT=3306,                   主库端口
    -> MASTER_LOG_FILE='mysql-bin.000014',  全备的position,就是从哪个事务开始自动同步
    ->  MASTER_LOG_POS=484,                 position号
    ->   MASTER_CONNECT_RETRY=10;           连接失败的睡眠秒数
Query OK, 0 rows affected, 2 warnings (0.37 sec)

开启主从复制线程
db02 [world]>start slave;
Query OK, 0 rows affected (0.01 sec)

检查
db02 [world]>show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: aaaa
                  Master_Port: 3306
                Connect_Retry: 10
              Master_Log_File: mysql-bin.000014
          Read_Master_Log_Pos: 484
               Relay_Log_File: db02-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000014
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes               两个yes才叫成功

进行测试
db01 [(none)]>create database llll;
Query OK, 1 row affected (0.00 sec)
db01 [(none)]>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| llll               |
| mysql              |
| performance_schema |
| sys                |
| test               |
| world              |
+--------------------+
7 rows in set (0.00 sec)

db02 [world]>show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| llll               |
| mysql              |
| performance_schema |
| sys                |
| test               |
| world              |
+--------------------+
7 rows in set (0.00 sec)

此时,主从复制成功

原理

1.change master to 时,主库的ip port user password binlog position写入到master。info进行记录
2.start slave时,从库启动IO线程和SQL线程
3.IO线程读取master.info信息,获取主库信息连接主库
4.主库会生成一个准备binlog DUMP线程,来响应从库
5.IO线程根据master.info记录的binlog文件名和position号,请求主库DUMP最新日志
6.DUMP线程检查主库的binlog日志,如果有新的,TP(传送)给从库的IO
7.IO将收到的日志存储到TCP/IP缓存,立即返回ACK给主库,主库工作完成
8.IO缓存中的数据,存储到relay-log(中继日志)日志文件,更新master.info文件binlog文件名和position号
9.SQL线程读取relay-log.info文件,获取到上次执行到relay-log的位置,作为起点,回放relay-log
10.SQL线程回放完成后,会更新relay-log.info文件
11.relay-log会有自动清理的功能
细节:
主库一旦有新的日志生成,会发送‘信号’给binlog dump,IO线程在请求

主从复制常见故障

IO线程
连接主库出错
检查用户,密码,IP,端口,
可以reset slave all  重新change master to
也有可能是主库连接数到达上限,主库太繁忙
二进制日志位置点不对

SQL线程
版本差异,参数设定不同
要创建的数据对象已在从库存在
要删除的对象在从库不存在
大部分原因是从库发生了写入操作
建议从库做只读
show variables like '%read_only%';

主从产生延时

主库
1.二进制写入不及时
2.CR的主从复制中,binlog_dump线程,事件为单元,串行传送二进制日志(5.5  5.6)
  (1):主库并发事务量大,主库可以并行,传送时是串行
  (2):主库发生了大事务,由于是串行传送,会产生阻塞后续的事务
解决:
1:从5.6开始,开启GTID,实现了GC(group commit)机制,可以并行传输日志给从库IO
2:5.7开始,不开启GTID,会自动维护匿名的GTID,可能实现GC,建议开启GTID
3.大事务拆分多个小事务,可以有效减少主从延时
从库
SQL线程导致的主从延时
在CR复制情况下,从库默认情况下只有一个SQL,只能串行回放事务
1,主库如果并发事务量较大,从库只能串行
2.主库发生了大事务,会阻塞后续的所有的事务的运行
解决
1.5.6版本开启GTID之后,加入了SQL多线程的特性,但是只能针对不同库下的事务进行并发回放
2.5.7版本开始GTID,在SQL方面,提供了基于逻辑时钟(logical_clock),binlog加入了seq_no机制
真正实现了基于事务级别的并发回放,这种技术称之为MTS
赞(0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

LNMP社群 不仅仅是技术

关于我们联系我们