一、主从复制基础
企业高可用标准(全年无故障率)
99.9% 故障率:0.1% 3642460=525.6min
99.99% 故障率:0.01%3642460=52.56min
99.999% 故障率:0.001%36424*60=5.256min
1.企业级高可用方案
负载均衡:有一定的高可用性。
LVS Nginx
主备系统:有高可用性,但是需要切换,是单活的架构
KeepAlive,MHA(日本人研发),MMM,TMHA
真正高可用(多活系统):
MySQL NDB CLuster
Oracle RAC
Sysbase cluster
InnoDB Cluster(MGR 5.7.17),
PXC ***
MGC ***
2.主从复制简介 **
2.1 基于二进制日志复制的
2.2 主库的修改操作会记录二进制日志
2.3 从库会请求新的二进制日志并回收,最终达到主从数据同步
2.4 主从复制核心功能
辅助备份,处理物理损坏
扩展新型的架构:高可用,高性能,分布式架构等。
3.主从复制的前提(主从复制的规划,实施过程)
3.1 至少2个数据库实例
3.2 主库要开启binlog,不同server_id,server_uuid
3.3 主库要有一个专门用作复制的用户(replication slave)
3.4 通过备份将源库数据补偿到从库
3.5 告知从库,用户名密码,ip,port,自动复制的起点。
3.6需要专门的复制线程(start slave)
4.搭建主从复制
4.1 准备多实例环境
[root@db01 ~]# systemctl start mysqld3307
[root@db01 ~]# systemctl start mysqld3308
[root@db01 ~]# mysql -S /data/3307/mysql.sock
[root@db01 ~]# mysql -S /data/3308/mysql.sock
4.2 检查 主库binlog,不同server_id,server_uuid
[root@db01 ~]# mysql -S /data/3307/mysql.sock -e "select @@log_bin;select @@server_id"
[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "select @@log_bin;select @@server_id"
4.3 主库创建复制用户
[root@db01 ~]# mysql -S /data/3307/mysql.sock -e "grant replication slave on *.* to repl@'10.0.0.%' identified by '123';"
[root@db01 ~]# mysql -S /data/3307/mysql.sock -e "select user,host from mysql.user where user='repl';"
+------+----------+
| user | host |
+------+----------+
| repl | 10.0.0.% |
+------+----------+
4.4 通过备份将源库数据补偿到从库
mysqldump -S /data/3307/mysql.sock -A -R -E --triggers --master-data=2 --single-transaction --max-allowed-packet=128M >/tmp/full.sql
[root@db01 ~]# mysql -S /data/3308/mysql.sock </tmp/fuul.sql
[root@db01 ~]#
4.5 告知从库,用户名,密码,IP,port,自动复制的起点
3.5 告知从库,用户名,密码,ip,port,自动复制的起点
# change master to 如果执行错误 记得stop slave
[root@db01 ~]# mysql -S /data/3308/mysql.sock
mysql> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.51',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='123',
-> MASTER_PORT=3307,
-> MASTER_LOG_FILE='mysql-bin.000003',
-> MASTER_LOG_POS=444,
-> MASTER_CONNECT_RETRY=10;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> /重试次数
vim /tmp/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.0000011', MASTER_LOG_POS=444;
4.6 启动主从线程
[root@db01 ~]# mysql -S /data/3308/mysql.sock
oldguo[(none)]>start slave;
4.7检测主从状态
[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@db01 ~]#
4.8 简单排错过程
[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G;"|grep "Last"
Last_Errno: 0
Last_Error:
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
[root@db01 ~]#
问题:
[root@db01 ~]# mysql -S /data/3308/mysql.sock
oldguo[(none)]>stop slave ;
oldguo[(none)]>reset slave all;
oldguo[(none)]> CHANGE MASTER TO xxxx
oldguo[(none)]>start slave;
5. 主从复制原理
5.1 主从复制过程中涉及到的文件
5.1.1 主库:
binlog 日志
/data/3307:
mysql-bin.000001
mysql-bin.000002
5.1.2 从库:
relaylog 中继日志
临时存储日志信息的文件
/data/3308/data
db01-relay-bin.000001
db01-relay-bin.000002
master.info 信息文件
主库信息文件
relay-log.info 信息文件
中继日志信息文件
5.2 主从复制中涉及到的线程
主库:
Binlog_Dump_Thread(二进制日志投递线程)
[root@db01 /data/3308/data]# mysql -S /data/3307/mysql.sock -e "show processlist;"
从库:
[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|egrep "Running:"
Slave_IO_Thread
Slave_SQL_Thread
6.主从复制的监控
从库
show slave status\G
过滤复制相关状态
mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Replicate_"
延时从库的状态信息
mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Delay:"
6.1 监控Gtid复制状态信息
mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "GTID"
7主从复制故障
7.1 IO线程故障
(1)读取master.info
损坏
信息错误 change master to 信息错误
(2)连接主库
网络
防火墙
主库没启动
连接数上限了
以上问题:
Slave_IO_Running:Connecting
Last_IO_Error:xxxx
排查方法:
通过复制用户,手工连接主库,看报错信息。
修复:
stop slave
reset slave all
change master to
start slave
(3) 请求日志
master.info 复制起点
主库:损坏,误删除等操作
二进制日志满了 清了主库的二进制日志 从库数据异常。
查看从库状态信息,主库信息,然后先停掉从库stop slave;重新清掉从库的信息reset slave all 接着再重新按着主库的起点和二进制日志号重新change master to 然后start slave启动从库。最后查一下状态,发现就好了。
(4)接收日志
relaylog损坏
修复:
stop slave
reset slave all
change master to
start slave
(5)更新master.info
7.2 SQL线程故障 *****
(1)relay.info
(2)回放relaylog中的日志 *****
SQL语句为什么会失败?
(1)语法,SQL_Mode
版本,sql_mode不一致
(2)DDL DML为什么会失败
create database /table 创建的对象已经存在了。
从库被提前写入了
处理方法(以从库为核心的处理方案):
方法一:
stop slave;
set global sql_slave_skip_counter=1
#将同步指针向下移动一个,如果多次不同步,可以重复操作。
start slave;
方法二:
/etc/my.cnf
slave-skip-errors=1032,1062,1007
常见错误代码:
1007:对象已存在
1032:无法执行DML
1062:主键冲突,或约束冲突
但是,以上操作有时是有风险的,最安全的做法就是重新构建主存,把握一个原则,一切以主库为主。
7.3 防止从库写入
(1)可以设置从库只读参数
show variables like "%read_only%";
mysql> show variables like '%read_only%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_read_only | OFF |
| read_only | OFF | 普通用户
| super_read_only | OFF | 对root用户
| transaction_read_only | OFF |
| tx_read_only | OFF |
+-----------------------+-------+
5 rows in set (0.01 sec)
(2)加中间件
读写分离
自己扩展 pt-xxx关于主从方面的工具
检查主从数据一致性
实现主从数据同步
8主从延时 *****
8.1 什么是主从延时
主库做的事,从库很久才执行。
8.2 主从延时的现象
(1)最直观:主库做变更,从库看数据状态。
(2)Seconds_Behind_Master:0(只能证明,有或者没有)
(3)计算日志的差异
8.3 主从延时的原因
8.3.1外部因素
网络
硬件
主库繁忙
版本差异
参数因素
8.3.2 内部因素
主库:
(1)二进制日志方面
二进制日志落地不及时
解决方案:
sync_binlog=1
可以将binlog单独存放高性能存储中
(2)Dump_T(默认是串行工作模式)
主库的事务量大
主库发生大事务
解决方法:
1.GTID模式
2.双一的保证
如何监控
主库:show master status;
从库 show slave status\G
Master_log_File:mysql-bin-000001
Read_Master_Log_Pos:484
从库
(1)IO线程方面
relaylog写入
解决方案:
relay_log_basename | /data/3307/data/db01-relay-bin |
| relay_log_index | /data/3307/data/db01-relay-bin.index
relay_log_purge 自动做清理
SQL线程方面(只有一个,串行回放)
默认SQL线程,只能逐条的回放SQL。
事务并发高
大事务
5.6版本 加入了多SQL复制
按照库(database)级别,进行并发回放SQL。
slave_parallel_workers=16
slave_parallel_type=DTATBASE
5.7版本 进行了多SQL复制加强(MTS)
真正按照事务级别,实现了多SQL线程回放。
slave_parallel_workers=16
slave_parallel_type=logical_clock
注意:必须依赖于GTID复制,并且binlog_format=row
如何监控:
(1)监控取了多少日志
show slave status\G
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 444
6.主从基础小结
6.1主从前提
6.2主从原理
6.3主从监控
show processlist
show slave status\G
master.info
relay.info
6.4主从故障
IO
连接
binlog
SQL
从库写入
DML,insert,update,delete
6.5主从延时
主
dump 串行:GTID ,双一 (从库和主库执行的gtid号是完全一致的) 并行
show slave status\G
Master_Master_log_Pos:1084
show master status\G
从
SQL 串行 :MTS
已经拿过来的日志:
show slave status\G
Master_Log_File:mysql-bin.000001
Read_Master_Log_Pos:1084
已经执行过多:
./db01-relay-bin.000003
920
mysql-bin.000001
800