主从复制安全性,需要从主库和从库两方面来配置一些保护措施。
主库宕机情况
innodb_flush_log_at_trx_commit 和 sync_binlog没有配置双1,导致并不能严格保证每个事务的日志的写入。
导致在主库提交的事务,并不一定已经写入硬盘,重启后,造成的日志的丢失
1. redo的trx_prepare未写入,但binlog写入,造成从库数据量比主库多。
2. redo的trx_prepare与commit都写入了,但是binlog未写入,造成从库数据量比主库少。
(1)涉及知识相关介绍
slave_master_info表
master.info文件或者mysql.slave_master_info表:用于保存从库的i/o线程连接主库的连接状态、账号、ip地址、端口、密码,以及i/o线程当前读取主库binlog的文件和位置信息(称为i/o线程信息日志)。
slave_relay_log_info表
relay_log.info文件或者mysql.slave_relay_log_info表:当从库的i/o线程从主库获取到最新的binlog事件信息后会先写入从库本地的relay log中,然后sql线程再去读取relay log解析并重放。
relay_log.info文件或者mysql.slave_relay_log_info表就是用于记录最新的relay log的文件和位置,以及sql线程当前重放的事件对应的主库binlog的文件和位置信息的(sql线程位置被称为sql线程信息日志)。
relay_log_recovery
当从库崩溃时,sql线程可能还有一部分relay log重放延迟。另外,i/o线程的位置也可能正处于一个事务的中间,并不完整,所以必须在从库上启用参数relay_log_recovery=on。
当启用该参数之后,从库崩溃恢复时会清理掉sql线程未重放完成的relay log,并以sql线程的位置为准重置i/o线程的位置,重新从主库请求。
sync_master_info 10000
如果你配置的master_info放置到文件io线程同步多少event后,落盘一次master_info 文件
(2)io线程高可靠性
io线程接收一个个的event ,将接收到的event,通过设置参数master_info_repository 可以将 master-info 信息(io线程接收到的位置,master_log_name和master_log_pos )
写入到文件( file )或者数据库( table )中。然后将 接收到的event写入relay log file
参数 sync_master_info=10000 表示 接收10000个event,写一次master-info
存在问题: master-info.log 和 relay-log 无法保证一致性。
relay-log-recover = 1
该参数表示当前接收到的relay-log全部删除,然后从sql线程回放到的位置重新拉取(sql线程通过配置后是可靠的)
(3)sql线程的安全性
sql线程造成的主从不一致
sync_relay_log_info = 10000
就是有可能sql已经被应用,但是sync_relay_log_info在文件内部没有即使刷新,导致重启的时候sql线程读取到了sync_relay_log_info没有更新的应用的位置,导致主从的数据不一致。
sql线程的安全性
relay_log_info_repository=table
可以将应用sql event和写入relay_log_info_repository的信息,划分到一个事务里面,而事务是具有原子性的,那么就可以保证从库的sql线程的安全性。
配置relay_log_info_repository参数后,sync_relay_log_info = 10000失效
(4)额外的优化
master_info_repository = table
将io同步的event位置信息写入到表里面,而不是文件内。
如果将master_info_repository = table配置到表内部,可以大幅度提交主从的复制的效率。
5.7内部表级别的多线程的复制,如果存储于文件,对于文件的io压力比较大,所以尽量将该信息写入到表的内部。
总结
从库三个参数可以保证复制的安全性
relay_log_recover = 1 (io线程)
relay_log_info_repository = table(sql线程)
master_info_repository = table