八,主从复制

1,主从复制简介

1.基于二进制日志复制的
2.主库的修改操作会记录二进制日志
3.从库会请求新的二进制日志并回放,最终达到主从数据同步
4.主从复制核心功能
    辅助备份,处理物理损坏                   
    扩展新型的架构:高可用,高性能,分布式架构等

2,高可用架构方案

负载均衡:有一定的高可用性 
LVS  Nginx
主备系统:有高可用性,但是需要切换,是单活的架构
KA ,   MHA, MMM
真正高可用(多活系统): 
NDB Cluster  Oracle RAC  Sysbase cluster   , InnoDB Cluster(MGR),PXC , MGC

3,主从复制前提

(1) 2个或以上的数据库实例
(2) 主库需要开启二进制日志 
(3) server_id要不同,区分不同的节点
(4) 主库需要建立专用的复制用户 (replication slave)
(5) 从库应该通过备份主库,恢复的方法进行"补课"
(6) 人为告诉从库一些复制信息(ip port user pass,二进制日志起点)
(7) 从库应该开启专门的复制线程

4,主从复制搭建

准备多实例

创建目录:
mkdir -p /data/330{7,8}/data

准备配置文件
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

cat > /data/3308/my.cnf <<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3308/data
socket=/data/3308/mysql.sock
log_error=/data/3308/mysql.log
port=3308
server_id=8
log_bin=/data/3308/mysql-bin
EOF

初始化数据;
mysqld --initialize-insecure  --user=mysql --datadir=/data/3307/data --basedir=/app/mysql
mysqld --initialize-insecure  --user=mysql --datadir=/data/3308/data --basedir=/app/mysql

systemd管理mysql:
cat >/etc/systemd/system/mysqld3307.service << EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3308.service << EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE = 5000
EOF

授权:
chown -R mysql.mysql /data/*

启动多实例

systemctl start mysqld3307.service
systemctl start mysqld3308.service

验证多实例:

[root@mister_f data]# mysql -p123 -S /data/3307/mysql.sock -e "select @@server_id"
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|           7 |
+-------------+
[root@mister_f data]# mysql -S /data/3308/mysql.sock -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
|           8 |
+-------------+
  

检查配置文件

1,检查是否开启了二进制日志
2,检查server_id是否不同,主库的server_id建议比从库的小

[root@mister_f data]# cat /data/3307/my.cnf 
[mysqld]
basedir=/application/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
[root@mister_f data]# cat /data/3308/my.cnf 
[mysqld]
basedir=/app/mysql
datadir=/data/3308/data
socket=/data/3308/mysql.sock
log_error=/data/3308/mysql.log
port=3308
server_id=8
log_bin=/data/3308/mysql-bin

创建主从复制用户(主库创建)

mysql -uroot -p123 -S /data/3307/mysql.sock -e "grant replication slave on *.* to repl@'10.0.0.%' identified by '123'"

备份主库数据

主库:
[root@mister_f data]# mysqldump -uroot -p123 -S /data/3307/mysql.sock -A --master-data=2 --single-transaction -R -E --triggers >/tmp/3307full.sql
 
从库:
[root@mister_f ~]# mysql -S /data/3308/mysql.sock
mysql> set sql_log_bin=0;
mysql> source /tmp/full.sql

告诉从库信息

mysql -S /data/3308/mysql.sock
help change master to 
找到这段信息
CHANGE MASTER TO
  MASTER_HOST='172.21.0.8',
  MASTER_USER='repl',
  MASTER_PASSWORD='123',
  MASTER_PORT=3307,
  MASTER_LOG_FILE='mysql-bin.000004',
  MASTER_LOG_POS=437,
  MASTER_CONNECT_RETRY=10;

从备份中找到这两段二进制日志信息:
[root@mister_f data]# vim  /tmp/3307full.sql 
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=437;
然后从库执行上面语句:

开启主从复制线程(IO,SQL)

mysql> start slave;

查看复制状态

查看两个线程是否是  YES
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.21.0.8
                  Master_User: repl
                  Master_Port: 3307
                Connect_Retry: 10
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 437
               Relay_Log_File: mister_f-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 437
              Relay_Log_Space: 530
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 7
                  Master_UUID: e5f625b1-b135-11eb-8a72-525400956ca6
             Master_Info_File: /data/3308/data/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

还阔以在主库创建库看一下是否同步过去:
主库:
[root@mister_f data]# mysql -uroot -p123 -S /data/3307/mysql.sock
mysql> create database wordpress charset utf8mb4;
Query OK, 1 row affected (0.01 sec)
从:

[root@mister_f ~]# mysql -S /data/3308/mysql.sock -e " show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| backup             |
| bin                |
| binlog             |
| gtid               |
| mysql              |
| performance_schema |
| sys                |
| test               |
| wordpress          |
| world              |
+--------------------+


5,主从复制原理

1.从库执行change master to 命令(主库的连接信息+复制的起点)
2.从库会将以上信息,记录到master.info文件
3.从库执行 start slave 命令,立即开启IO_T和SQL_T
4. 从库 IO_T,读取master.info文件中的信息,获取到IP,PORT,User,Pass,binlog的位置信息
5. 从库IO_T请求连接主库,主库专门提供一个DUMP_T,负责和IO_T交互
6. IO_T根据binlog的位置信息(mysql-bin.000004 , 444),请求主库新的binlog
7. 主库通过DUMP_T将最新的binlog,通过网络TP给从库的IO_T
8. IO_T接收到新的binlog日志,存储到TCP/IP缓存,立即返回ACK给主库,并更新master.info
9.IO_T将TCP/IP缓存中数据,转储到磁盘relaylog中.
10. SQL_T读取relay.info中的信息,获取到上次已经应用过的relaylog的位置信息
11. SQL_T会按照上次的位置点回放最新的relaylog,再次更新relay.info信息
12. 从库会自动purge应用过relay进行定期清理
补充说明:
一旦主从复制构建成功,主库当中发生了新的变化,都会通过dump_T发送信号给IO_T,增强了主从复制的实时性.
image.png

6,主从复制监控

命令:
mysql> show slave status\G

主库相关的信息(master.info)

Master_Host: 172.21.0.8
Master_User: repl
Master_Port: 3307
Connect_Retry: 10
重点关注这两,看是否和主库的binlog文件相对应
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1086

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |     1086 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

从库relay应用相关的(relay.info)

Relay_Log_File: mister_f-relay-bin.000002
Relay_Log_Pos: 969
Relay_Master_Log_File: mysql-bin.000004
在从库的数据路径下
-rw-r----- 1 mysql mysql      121 May 22 15:07 master.info
-rw-r----- 1 mysql mysql      210 May 22 11:40 mister_f-relay-bin.000001
-rw-r----- 1 mysql mysql      969 May 22 11:48 mister_f-relay-bin.000002
-rw-r----- 1 mysql mysql       56 May 22 11:40 mister_f-relay-bin.index
-rw-r----- 1 mysql mysql       63 May 22 11:48 relay-log.info

从库线程运行状态(一般用于排错)

Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_IO_Errno: 0
Last_IO_Error: 
Last_SQL_Errno: 0
Last_SQL_Error:

过滤复制相关的

Replicate_Do_DB: 
Replicate_Ignore_DB: 
Replicate_Do_Table: 
Replicate_Ignore_Table: 
Replicate_Wild_Do_Table: 
Replicate_Wild_Ignore_Table: 

从库延时主库的时间

 Seconds_Behind_Master: 0

延时从库

SQL_Delay: 0
SQL_Remaining_Delay: NULL

GTID复制相关的

Retrieved_Gtid_Set: 
Executed_Gtid_Set: 
Auto_Position: 0

7,主从复制故障

IO线程故障

1,IO线程连接不上
网络,连接信息错误或变更了,防火墙,连接数上线
一般IO线程会显示:connecting状态
排查方案:
使用手工复制用户登录出现一下错误时:
[root@mister_f ~]# mysql -urepl -p1234 -h172.21.0.8 -P3307
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Unknown error 1045
[root@mister_f ~]# mysql -urepl -p1234 -h172.21.0.9 -P3307
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@mister_f ~]# mysql -urepl -p1234 -h172.21.0.8 -P3309
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2003 (HY000): Can't connect to MySQL server on '172.21.0.8' (111)
解决方案:
1. stop slave 
2. reset slave all;
3. change master to 
4. start slave

2,请求binlog请求不到
  binlog没开启
  binlog损坏或不存在
  主库执行了reset master操作

处理方法:(从库执行)
stop slave ;
reset slave all; 
CHANGE MASTER TO 
MASTER_HOST='172.21.0.8',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=1086,
MASTER_CONNECT_RETRY=10;
start slave;

SQL线程故障

relay-log损坏
回放relaylog
研究一条SQL语句为什么执行失败?
insert delete  update     ---> t1 表 不存在
create table  oldboy     ---> oldboy 已存在
约束冲突(主键,唯一键,非空..)

合理处理方法: 
把握一个原则,一切以主库为准进行解决.
如果出现问题,尽量进行反操作
最直接稳妥办法,重新构建

暴力的解决方法
方法一:
stop slave; 
set global sql_slave_skip_counter = 1;
start slave;

#将同步指针向下移动一个,如果多次不同步,可以重复操作。
start slave;
方法二:
/etc/my.cnf
slave-skip-errors = 1032,1062,1007
常见错误代码:
1007:对象已存在
1032:无法执行DML
1062:主键冲突,或约束冲突
但是,以上操作有时是有风险的,最安全的做法就是重新构建主从。把握一个原则,一切以主库为主.
为了很程度的避免SQL线程故障主
(1) 从库只读
mysql> show variables like '%read_only%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| read_only                     | OFF   |
| super_read_only               | OFF   |
+-------------------------------+-------+
6 rows in set (0.01 sec)

read_only
super_read_only
(2) 使用读写分离中间件
atlas 
mycat
ProxySQL 
MaxScale从

8,主从延时监控及原因

主库方面原因

(1) 二进制日志写入不及时
mysql> select @@sync_binlog;
+---------------+
| @@sync_binlog |
+---------------+
|             1 |
+---------------+
想要一提交事务就写入binlog需设置sync_binlog=1
(2) CR的主从复制中,binlog_dump线程,事件为单元,串行传送二进制日志(5.6 5.5)

1. 主库并发事务量大,主库可以并行,传送时是串行
2. 主库发生了大事务,由于是串行传送,会产生阻塞后续的事务.

解决方案:
1.  5.6 开始,开启GTID,实现了GC(group commit)机制,可以并行传输日志给从库IO
2.  5.7 开始,不开启GTID,会自动维护匿名的GTID,也能实现GC,我们建议还是认为开启GTID
3. 大事务拆成多个小事务,可以有效的减少主从延时.

从库方面原因

(1) 传统复制(Classic)中 
如果主库并发事务量很大,或者出现大事务
由于从库是单SQL线程,导致,不管传的日志有多少,只能一次执行一个事务.
5.6 版本,有了GTID,可以实现多SQL线程,但是只能基于不同库的事务进行并发回放.(database模式针对库进行并发) 5.6多线程是基于库
5.7 版本中,有了增强的GTID,增加了seq_no,增加了新型的并发SQL线程模式(logical_clock),MTS技术,5.7中多线程是基于事务
(2) 主从硬件差异太大
(3) 主从的参数配置
(4) 从库和主库的索引不一致
(5) 版本有差异

主从延时监控的原因

主库方面监控原因
主库:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |     1790 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
从库:
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1790
这两个号码对比可以看出是是主库原因

从库监控方面原因:
从库:
首先可以看从库从主库拿了多少日志过来
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1790

查看从库执行了多少
Relay_Log_File: mister_f-relay-bin.000002
Relay_Log_Pos: 1673

用这两个号码和binlog的号码相比较如果没有相差多少说明主从没有延时,如果差别很大说明有什么大事务阻塞,然后找到阻塞的sql语句进行优化
Exec_Master_Log_Pos: 1790
Relay_Log_Space: 1883

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 0.企业高可用性标准 *** 0.1 全年无故障率(非计划内故障停机) 99.9%---->0.001*365*2...
    小一_d28d阅读 288评论 0 0
  • 一、主从复制基础 企业高可用标准(全年无故障率) 99.9% 故障率:0.1% 364...
    我要笑阅读 214评论 0 0
  • 主从复制基础 企业高可用性标准全年无故障率(非计划内故障停机) 企业级高可用架构方案 主从复制简介 ☆☆☆☆☆ 说...
    酷酷的伟阅读 374评论 1 0
  • 主从复制基础 (!=同步,异步的工作模式) 1. 主从复制介绍(Master-Slave Replication)...
    Gq赵阅读 636评论 0 0
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 123,982评论 2 7