什么是主从同步
所谓主从同步,是指两个或多个数据库数据一致,一个库数据的更新会同步更新到所有的数据库上。
主从同步的必要性
在实际项目中,为了产品的高可用,我们常常会搭建多台数据库,实现冗余,达到负载均衡、容灾等目的。比如,只有一台数据库的时候,大量的用户请求,或者由于一些硬件故障导致的宕机,将会导致整个应用的crash,此时如果能够有多余的服务器提供服务,就可以将请求分配到别的可用的服务器,从而保证用户的正常使用!摆在我们跟前的问题就是,如何能够保证两台或多台数据库服务器上数据的一致性!
主从同步的作用
- 服务器容灾,一旦主服务器出现问题,可以快速切换到从服务器,继续提供服务
- 负载分担,查询请求可以交给从服务器,从而减少主服务器的压力
- 数据备份,在从服务器上进行数据备份,以避免备份期间主服务器性能收到影响
主从同步原理
- 主服务器验证连接。
- 主服务器为从服务器开启一个线程。
- 从服务器将主服务器日志的偏移位告诉主服务器。
- 主服务器检查该值是否小于当前二进制日志偏移位。
- 如果小于,则通知从服务器来取数据。
- 从服务器持续从主服务器取数据,直至取完,这时,从服务器线程进入睡眠,主服务器线程同时进入睡眠
- 当主服务器有更新时,主服务器线程被激活,并将二进制日志推送给从服务器,并通知从服务器线程进入工作状态。
- 从服务器SQL线程执行二进制日志,随后进入睡眠状态
从库生成两个线程,一个I/O线程,一个SQL线程;I/O线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中;主库会生成一个 log dump 线程,用来给从库I/O线程传binlog;SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;
master主库配置
如何能够保证两台或多台数据库服务器上数据的一致性呢,我已经准备好主从库的相关环境,接下来完成主从配置,针对主库配置
- 打开修改my.cnf
server-id=128 #(一个集群中必须保证唯一,一般取ip最后一段)
#开启binlog,记录对数据发生或潜在发生更改的SQL语句,并以二进制的形式保存在磁盘中
log-bin=mysql-bin
- 创建同步账号并授权
create user '用户名'@'%' identified with mysql_native_password by '密码'; grant replication slave on *.* to '用户名'@'%';
- 如有需要,可以重置主库从库日志 reset master/slave
- 查询主数据库状态 show master status
slave从库配置
- 打开修改my.cnfmy.cnf/ini中server-id
server-id=129 #从库可以打开logbin,也可以不打开 relay-log-index=slave-relay-bin.index relay-log=slave-relay-bin
- 启动服务配置同步参数
change master to master_host='192.168.1.128', #master IP master_user='', #master数据库通过GRANT授权的账号 master_password='', #master数据库通过GRANT授权的密码 master_port=3306, #master数据库的端口号 master_log_file='mysql-bin.000010', #master数据库中通过show master status显示的File名称 master_log_pos=16306 #master数据库的通过show master status显示的Position的值,表示从1144操作的步骤开始执行同步
- 启动主从同步进程
start slave
- 检查状态
show slave status
Slave_IO_Running:负责从库去主库读取二进制日志,并写入到从库的中继日志
Slave_SQL_Running:负责将中继日志换成SQL语句执行
以上两个状态都为yes即OK
主库配置同步策略
- 不允许跨库
--binlog-do-db=db_name --binlog-ignore-db=db_name
从库配置同步策略
- replicate-do-db=database1 //同步的数据库
- replicate-do-db=database2
- replicate-ignore-db=mysql //被忽略的数据库
- replicate-do-table=db_name.tbl_name
- replicate-ignore-table=db_name.tbl_name
以下都允许跨库
- replicate-wild-do-table=db_name.tbl_name
- replicate-wild-ignore-table=db_name.tbl_name
使用主从同步来备份(测试)
- 主库备份
mysqldump -uroot -p test>dump.sql scp dump.sql root@192.168.134.129:路径
- 从库恢复
方法一 mysql -uroot -p test<dump.sql 方法二 [root@localhost ~]# mysql -uroot -p test mysql> source dump.sql
操作主库数据进行主从同步测试
常见问题
Slave_IO_Running: NO
这是一个很常见的错误(我也曾对这个错误咬牙切齿),总结起来就三个原因:
- 主服务器的网络不通,或者主服务器的防火墙拒绝了外部连接3306端口(检查网络,开放端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent firewall-cmd --reload)
- 在配置从服务器时,输错了ip地址和密码,或者主服务器在创建用户时写错了用户名和密码
- 在配置从服务器时,输错了主服务器的二进制日志信息,出现slave的position比master大
slave上执行以下操作:
- stop slave
- reset slave
- change master(比如:change master to master_host='192.168.1.128',master_user='',master_password='',master_log_file='mysql-bin.000010',MASTER_LOG_POS=16306)
- start slave
虽然上述可以解决问题,但是可能会导致数据不统一,所以建议导出主库数据,然后在从库恢复。