1、延时从库
1、逻辑损坏怎么办?
延时从库:从库落后于主库一段时间,一般企业建议3-6小时;利用延时从库恢复
原理:IO线程不延时,SQL线程延时执行;
# 开启延时从库
stop slave;
change master to master_delay = 300; //单位为秒
start slave;
show slave status\G
SQL_Delay:300
# 关闭延时从库
stop slave;
change master to master_delay = 0; //单位为秒
start slave;
2、主库误操作,怎么使用延时从库恢复?
- 立即停止主库业务,立即停止从库SQL线程
stop slave sql_thread; - 手工模拟sql线程工作,并截至到误操作之前
(1)读取relay-log.info,截取到上次执行到的位置,作为继续执行relay-log的起点 ;
(2)分析relay-log内容,获取到误操作之前位置点。
(3)截取这段日志,恢复到从库 - 从库切为主库,原主库切为从库
故障模拟:
(1)模拟数据
pc [(none)]>create database delay charset utf8;
pc [(none)]>use delay;
pc [delay]>create table t1(id int);
pc [delay]>insert into t1 values(1),(2),(3);
pc [delay]>commit;
pc [delay]>drop database delay;
(2)停止从库sql线程
pc [test]>stop slave sql_thread;
(3)读取从库relay-log 信息
pc [test]>show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.51
Master_User: repl
Master_Port: 3307
Connect_Retry: 10
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1422
Relay_Log_File: db01-relay-bin.000002
Relay_Log_Pos: 283
起始位置为283;
- 找到误删除位置
pc [test]>show relaylog events in 'db01-relay-bin.000002';
+-----------------------+-----+-------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-----------------------+-----+-------------+-----------+-------------+---------------------------------------+
···
| db01-relay-bin.000002 | 692 | Query | 7 | 1422 | drop database delay |
+-----------------------+-----+-------------+-----------+-------------+---------------------------------------+
10 rows in set (0.00 sec)
drop启始位置为692;
(4)截取relay-log日志
cd /data/3308/data/
mysqlbinlog --start-position=283 --stop-position=692 db01-relay-bin.000002>/tmp/relay.log
(5)恢复relay-log
mysql -uroot -S /data/3308/mysql.sock //登录从库
source /tmp/relay.log
(6)此时从库的数据是完整的;从库切换为主库,原主库切换为从库
3、过滤复制
4、不能保证主库做的操作,从库一定能做。
5、高可用?自动 failover
2、半同步复制
定义:尽可能保证主从数据一致性,会牺牲主库一定的性能;有设定超时时间,10秒钟,如果从库超过这个时间没有返回ACK,强制切换为异步复制过程。
半同步复制存在的原因:
当主库dump线程将binlog日志发送给从库IO线程,存储到TCP/IP缓存中,如果此时从库宕机或关机了,存在缓存中的数据有丢失的风险;
半同步复制:当从库存在TCP/IP缓存中的数据写入到relay-log日志中,返回给主库一个ACK确认,主库才会commit操作;
有一定数据安全性的保证,但主从数据不是完全一致性。
5.6以后半同步复制改为group commit,性能提高,可以推荐使用半同步。同步复制:当从库SQL线程执行完relay-log日志,返回给主库一个ACK确认,主库commit,才会执行下一个操作;会牺牲主库的性能;
也就是说当主库传给从库一个事务,只有当从库执行完这个事务与主库一致,主库才会执行下一个操作。
配置半同步复制
# 加载插件,如果要永久生效,加到配置文件中
主:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
从:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
# 查看是否加载成功:
show plugins;
# 启动:
主:
SET GLOBAL rpl_semi_sync_master_enabled = 1;
从:
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
# 重启从库上的IO线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
# 查看是否在运行
主:
show status like 'Rpl_semi_sync_master_status';
从:
show status like 'Rpl_semi_sync_slave_status';
3、过滤复制
定义:写操作在主库发生,将多个从库的业务拆分,即A数据复制1从库,B数据复制到2从库。
show master status;
Binlog_Do_DB //白名单,binlog记录的库
Binlog_Ignore_DB //黑名单,binlog忽略的库
pc [world]>show slave status\G
*************************** 1. row ***************************
Replicate_Do_DB: //白名单,复制的库
Replicate_Ignore_DB: //黑名单,忽略的库
Replicate_Do_Table: //表的白名单,复制的表
Replicate_Ignore_Table: //表的黑名单,忽略的表
Replicate_Wild_Do_Table: //模糊的白名单,t**,以t开头的表复制
Replicate_Wild_Ignore_Table: //模糊的黑名单,忽略t开头的表复制
2.1 过滤复制配置
前提: 主从复制已开启,在从库配置
[root@db01 ~]# vim /data/3309/my.cnf
[mysqld]
replicate_do_db=ppt
replicate-do-table=test.t1
replicate-wild-do-table=test.t*
# 重启从库
[root@db01 ~]# systemctl restart mysqld3309
or
mysqladmin -S /data/3308/mysql.sock shutdown
mysqld_safe --defaults-file=/data/3308/my.cnf &
主库测试:
Master [(none)]>create database word;
Query OK, 1 row affected (0.00 sec)
Master [(none)]>create database ppt;
Query OK, 1 row affected (0.00 sec)
Master [(none)]>create database excel;
Query OK, 1 row affected (0.01 sec)
4、 GTID复制
3.1 环境准备
- 停库
[root@db01 ~]# /etc/init.d/mysqld stop - 删除data目录
[root@db01 ~]# rm -fr /application/mysql/data/* - 备份3台机器的配置文件
mv /etc/my.cnf /tmp - 初始化配置文件
master:10.0.0.51
vim /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log_error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
skip-name-resolve
server_id=51
gtid-mode=on
port=3306
autocommit=0
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock
prompt=\\ pc [\\d]>
slave:10.0.0.52
vim /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log_error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
skip-name-resolve
server_id=52
gtid-mode=on
port=3306
autocommit=0
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock
prompt=\\ pc [\\d]>
slave:10.0.0.53
vim /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log_error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
skip-name-resolve
server_id=53
gtid-mode=on
port=3306
autocommit=0
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock
prompt=\\ pc [\\d]>
- 初始化MySQL
[root@db01 ~ ]# cd /application/mysql/scripts/
[root@db01 scripts]# ./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data - 启动数据库
root@db01 scripts]# /etc/init.d/mysqld start
3.2 Gtid 复制介绍
1、介绍
GTID(Global Transaction ID)是对于一个已提交事务的唯一编号,并且是一个全局(主从复制)唯一的编号。
它的官方定义如下:
GTID构成 = source_id :transaction_id (server_uuid 也叫 uuid,transaction_id :事务编号)
server-uuid=880e1664-498a-11ea-87bd-000c29a94591:26
功能:保证主从数据一致性以及主库切换更为方便。
依赖于GTID的新功能:group commit;多线程(从库SQL);MGR
2、什么是sever_uuid,和Server-id 区别?
server_uuid 也叫 uuid ,默认是在第一次启动数据库时,自动生成的;删除此文件,重启数据库,会生成新的文件。
位置:/application/mysql/data/auto.cnf
核心特性: 全局唯一,具备幂等性:执行过的事务,不会再重复执行。
3、GTID参数
gtid-mode=on //启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true //强制GTID的一致性
log-slave-updates=1 //slave更新是否记入日志
4、GTID复制与普通复制区别
第一次开启主从复制,IO线程读取relay-log日志,发现是空的,会读取主库二进制日志,请求所有复制。
下次复制时,自动获取relay-log最后一条日志位置(包含GTID号),获取新的事务,不需要再读取master.info信息
CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=444,
MASTER_CONNECT_RETRY=10;
change master to
master_host='10.0.0.51',
master_user='repl',
master_password='123' ,
MASTER_AUTO_POSITION=1;
start slave;
(0)在主从复制环境中,主库发生过的事务,在全局都是由唯一GTID记录的,更方便Failover
(1)额外功能参数(3个)
(2)change master to 的时候不再需要binlog 文件名和position号,MASTER_AUTO_POSITION=1;
(3)在复制过程中,从库不再依赖master.info文件,而是直接读取最后一个relaylog的 GTID号
(4) mysqldump备份时,默认会将备份中包含的事务操作,以以下方式
SET @@GLOBAL.GTID_PURGED='8c49d7ec-7e78-11e8-9638-000c29ca725d:1';
告诉从库,我的备份中已经有以上事务,你就不用运行了,直接从下一个GTID开始请求binlog就行。
5、GTID严格要求事务的连续性,当GTID从库宕机、中断主库的复制,主库仍在发送事务,此时需要在从库提交空事务,填补空缺日志,否则无法继续复制。
注入空事务的方法:
stop slave;
set gtid_next='880e1664-498a-11ea-87bd-000c29a94591:1-2';
begin;
commit;
set gtid_next='AUTOMATIC';
start slave;
这里的xxxxx:N 也就是你的slave sql thread 报错的GTID ,或者说是你想要跳过的GTID.最好的解决方法:重新构建主从环境
3.3 GTID复制配置
前提:清理完环境,配置文件配置好,初始化数据库
# master:
grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
# slave:
reset maser; //清理之前的relay-log
change master to
master_host='10.0.0.51',
master_user='repl',
master_password='123' ,
MASTER_AUTO_POSITION=1;
start slave;
3.4 查看GTID
# 主库
pc [(none)]>show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000011 | 191 | | | 880e1664-498a-11ea-87bd-000c29a94591:1-2 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
# 从库
pc [(none)]> pc [(none)]>show slave status\G
*************************** 1. row ***************************
···
Retrieved_Gtid_Set: //从库执行到的GTID号
Executed_Gtid_Set: 880e1664-498a-11ea-87bd-000c29a94591:1-2