MySQL主从复制是MySQL高可用架构的基础,也是每个后端开发者和运维人员必须掌握的技能。通过主从复制,可以实现数据备份、读写分离、故障转移、高可用等功能,大大提升数据库的可靠性和性能。但是很多初学者对主从复制的原理和配置不太清楚,不知道从哪里入手。
今天就来写一个MySQL主从复制的入门指南,从零开始,讲清楚主从复制的原理、作用、类型、配置步骤、常见问题和最佳实践,希望能帮到想学习MySQL主从复制的朋友。
一、什么是MySQL主从复制
MySQL主从复制,就是将一台MySQL服务器(主服务器,Master)的数据,复制到另一台或多台MySQL服务器(从服务器,Slave)上的过程。复制是异步进行的,主服务器上的数据变更,会通过二进制日志(binlog)传递到从服务器,从服务器应用这些日志,从而保持和主服务器的数据一致。
主从复制的基本流程是这样的:
- 主服务器在数据变更的时候,会将变更记录写入二进制日志(binlog)。
- 从服务器的IO线程,会连接到主服务器,请求读取主服务器的binlog,然后将binlog写入到自己的中继日志(relay log)中。
- 从服务器的SQL线程,会读取中继日志中的事件,然后在从服务器上执行这些事件,从而将数据变更应用到从服务器上。
这个过程是异步的,主服务器不需要等待从服务器复制完成,就可以继续处理请求,所以主从复制不会影响主服务器的性能。但是因为是异步的,所以从服务器的数据可能会有一定的延迟,特别是在主服务器写入量很大的时候,延迟可能会比较明显。
主从复制是MySQL内置的功能,不需要额外的软件,只需要简单的配置就可以使用,而且非常稳定可靠,是MySQL高可用架构的基础。
二、为什么要用主从复制,它有什么作用
主从复制的作用很多,主要有以下几个方面:
1. 数据备份和容灾
这是主从复制最基本的作用。通过主从复制,可以将主服务器的数据实时复制到从服务器上,相当于有了一个实时的备份。如果主服务器出了故障,比如硬盘损坏、系统崩溃,数据不会丢失,因为从服务器上还有一份完整的数据,可以快速恢复。
而且从服务器可以部署在不同的机房、不同的地域,实现异地容灾,即使主服务器所在的机房整个出了问题,从服务器的数据还在,业务可以快速切换到从服务器,保证业务不中断。
2. 读写分离,提升性能
这是主从复制最常用的作用。通过主从复制,可以实现读写分离,写操作(增删改)在主服务器上执行,读操作(查询)在从服务器上执行。这样可以将读压力分散到从服务器上,大大减轻主服务器的压力,提升整个系统的性能和并发能力。
特别是对于读多写少的应用,比如博客、新闻、电商商品展示等,读操作占了绝大部分,用读写分离的效果非常好,可以加多个从服务器来分担读压力,水平扩展读能力。
3. 高可用和故障转移
通过主从复制,可以实现MySQL的高可用。如果主服务器出了故障,可以快速将一个从服务器提升为主服务器,继续提供服务,从而实现故障转移,保证业务不中断。
当然,主从复制本身不能自动实现故障转移,需要配合其他工具,比如MHA、Keepalived、Orchestrator等,来实现自动故障检测和转移。但是主从复制是高可用的基础,没有主从复制,就无法实现快速的故障转移。
4. 数据分析和报表
可以用一个从服务器专门用来做数据分析、报表统计、数据挖掘等操作,这些操作通常查询量很大,很消耗资源,如果在主服务器上执行,会影响主服务器的性能。放在从服务器上执行,就不会影响主服务器,而且从服务器的数据和主服务器是一致的,分析结果也是准确的。
5. 数据分发
可以将主服务器的数据复制到多个从服务器,分布在不同的地域,供不同的业务使用,实现数据的就近访问,提升访问速度。比如全国性的业务,可以在不同的地区部署从服务器,当地的用户读当地的从服务器,速度更快,体验更好。
总的来说,主从复制的作用非常多,是MySQL架构中不可或缺的一部分,不管是小项目还是大项目,都建议用主从复制,至少有一个从服务器做备份,保证数据安全。
三、主从复制的类型
MySQL主从复制有几种不同的类型,根据复制的方式和数据格式,可以分为以下几种:
1. 基于语句的复制(Statement-Based Replication,SBR)
这种复制方式,主服务器会将执行的SQL语句写入binlog,从服务器执行这些SQL语句,从而实现数据复制。优点是binlog文件小,传输快,而且便于审计,因为记录的是原始的SQL语句。缺点是有些SQL语句可能有不确定性,比如UUID()、NOW()、AUTO_INCREMENT等,在主服务器和从服务器上执行的结果可能不一样,导致数据不一致。还有一些复杂的SQL,比如存储过程、触发器,也可能有问题。
2. 基于行的复制(Row-Based Replication,RBR)
这种复制方式,主服务器会将数据行的变更写入binlog,记录的是哪一行数据被修改了,修改成了什么样子,从服务器直接应用这些行变更。优点是数据准确,不会有不确定性的问题,任何数据变更都能准确复制,包括存储过程、触发器等。缺点是binlog文件比较大,特别是批量更新的时候,会记录很多行的变更,传输慢,而且不便于审计,因为看不到原始的SQL语句。
3. 混合模式复制(Mixed-Based Replication,MBR)
这种复制方式,结合了上面两种方式的优点,一般情况下用基于语句的复制,当遇到有不确定性的SQL语句时,自动切换到基于行的复制。这样既保证了数据的准确性,又兼顾了binlog的大小和传输效率,是目前推荐使用的复制方式。
MySQL 5.7及以上版本,默认的binlog格式是ROW,也就是基于行的复制,因为这种方式最安全,数据最准确。当然,也可以根据自己的需求选择其他格式,但是一般推荐用ROW格式,或者MIXED格式。
除了按数据格式分类,主从复制还可以按拓扑结构分类,常见的有:
- 一主一从:一个主服务器,一个从服务器,最简单的架构,适合小项目。
- 一主多从:一个主服务器,多个从服务器,适合读多写少的场景,可以分担读压力。
- 多主复制:多个主服务器,互相复制,适合多机房部署,但是配置复杂,容易有冲突,一般不推荐。
- 级联复制:主服务器复制到一个从服务器,这个从服务器再复制到其他从服务器,也就是从服务器同时也是主服务器,适合从服务器很多的场景,可以减轻主服务器的压力。
初学者建议从一主一从开始,掌握了基本原理和配置之后,再尝试更复杂的架构。
四、主从复制的配置步骤
讲完了原理和类型,现在来讲讲具体怎么配置MySQL主从复制。以一主一从为例,MySQL版本5.7,操作系统Linux。
第一步:准备两台服务器
准备两台服务器,一台做主,一台做从,都安装好MySQL,版本最好一致,或者从服务器的版本不低于主服务器。两台服务器网络互通,主服务器的3306端口对从服务器开放。
假设主服务器IP是192.168.1.10,从服务器IP是192.168.1.20。
第二步:配置主服务器
编辑主服务器的MySQL配置文件my.cnf(一般在/etc/my.cnf或者/etc/mysql/my.cnf),在[mysqld]部分添加以下配置:
[mysqld]
# 服务器唯一ID,主从服务器不能重复
server-id = 1
# 开启二进制日志
log-bin = mysql-bin
# binlog格式,推荐ROW
binlog_format = ROW
# 需要复制的数据库,如果不配置就是复制所有数据库
# binlog-do-db = testdb
# 不需要复制的数据库
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema配置好之后,重启MySQL服务:service mysqld restart。
然后登录MySQL,创建一个用于复制的用户,给从服务器使用:
CREATE USER 'repl'@'192.168.1.20' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.20';
FLUSH PRIVILEGES;然后查看主服务器的binlog状态,记录下File和Position的值,后面配置从服务器的时候要用:
SHOW MASTER STATUS;输出大概是这样的:
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 154 | | mysql |
+------------------+----------+--------------+------------------+记录下File是mysql-bin.000001,Position是154。
第三步:配置从服务器
编辑从服务器的MySQL配置文件my.cnf,在[mysqld]部分添加以下配置:
[mysqld]
# 服务器唯一ID,不能和主服务器重复
server-id = 2
# 开启中继日志
relay-log = relay-bin
# 从服务器只读,防止误写(超级用户还是可以写)
read_only = 1
# 复制的数据库,如果不配置就是复制所有
# replicate-do-db = testdb
# 不复制的数据库
replicate-ignore-db = mysql
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema配置好之后,重启MySQL服务:service mysqld restart。
然后登录从服务器的MySQL,配置主服务器的信息,开始复制:
CHANGE MASTER TO
MASTER_HOST='192.168.1.10',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;这里的MASTERLOGFILE和MASTERLOGPOS就是刚才在主服务器上查到的File和Position的值。
然后启动从服务器的复制:
START SLAVE;然后查看从服务器的复制状态:
SHOW SLAVE STATUS\G重点看这两个值:
SlaveIORunning: Yes:IO线程运行正常SlaveSQLRunning: Yes:SQL线程运行正常
如果这两个都是Yes,说明主从复制配置成功了。如果有一个是No,或者有错误信息,就需要排查问题。
第四步:测试主从复制
配置成功之后,可以测试一下。在主服务器上创建一个数据库,创建一张表,插入一条数据,然后去从服务器上查看,看看数据是不是已经复制过来了。如果复制过来了,说明主从复制正常工作。
如果主服务器上已经有数据了,需要先把主服务器的数据导出,导入到从服务器,然后再配置复制,不然从服务器没有历史数据,只有配置之后的新数据。导出数据可以用mysqldump,注意要加--master-data参数,记录binlog的位置,导入到从服务器之后,直接用这个位置配置复制就行。
五、常见问题和排查方法
主从复制配置过程中,经常会遇到各种问题,这里总结几个常见的问题和排查方法。
1. SlaveIORunning是No
这说明IO线程有问题,一般是连接主服务器失败,常见的原因有:
- 主服务器IP、端口、用户名、密码配置错误
- 从服务器网络不通,连不上主服务器
- 主服务器的防火墙没有开放3306端口
- 复制用户没有权限,或者IP限制不对
- 主服务器的binlog文件不存在,或者位置不对
排查方法:先在从服务器上用mysql命令行连接主服务器,看看能不能连上,用户名密码对不对,权限够不够。如果连不上,检查网络、防火墙、端口。如果能连上,检查CHANGE MASTER TO的配置对不对,特别是MASTERLOGFILE和MASTERLOGPOS是不是和主服务器的一致。
2. SlaveSQLRunning是No
这说明SQL线程有问题,一般是执行中继日志的时候出错了,常见的原因有:
- 主从数据不一致,主服务器上有的数据从服务器没有,或者反过来
- 从服务器上有人手动写了数据,和主服务器复制过来的数据冲突
- 主键冲突,重复插入
- 表结构不一致,主服务器上的表和从服务器上的表结构不一样
- 执行了不支持的SQL语句
排查方法:看SHOW SLAVE STATUS里的Last_Error信息,会告诉你具体是什么错误,在哪个文件哪个位置出错了。根据错误信息去排查,一般是数据不一致导致的。如果错误不严重,可以跳过这个错误,继续复制:
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;但是这个方法只是跳过错误,不能解决根本问题,如果数据不一致,后面还会出错。最好的方法是重新配置主从复制,把主服务器的数据重新导出导入到从服务器,保证数据一致。
3. 主从延迟大
这是很常见的问题,从服务器的数据比主服务器慢很多,常见的原因有:
- 主服务器写入量太大,从服务器跟不上
- 从服务器性能差,CPU、内存、磁盘IO不够
- 网络带宽不够,binlog传输慢
- 从服务器上有大量的查询,占用了资源,影响了SQL线程的执行
- 大事务,主服务器上执行了一个很大的事务,从服务器执行的时候需要很长时间
- 表没有主键,基于行的复制的时候,从服务器更新数据需要全表扫描,很慢
排查和解决方法:
- 优化从服务器的性能,提升硬件配置
- 减少从服务器上的查询,或者加更多的从服务器分担读压力
- 优化网络,保证主从服务器之间的带宽
- 避免大事务,把大事务拆分成小事务
- 确保所有表都有主键,这对基于行的复制很重要
- 用并行复制,MySQL 5.7支持基于组的并行复制,可以提升复制速度
4. 主服务器宕机了怎么办
如果主服务器宕机了,需要把从服务器提升为主服务器,继续提供服务。步骤是:
- 确认从服务器已经把所有的中继日志都执行完了,数据是最新的
- 在从服务器上执行STOP SLAVE,然后RESET MASTER,清除从服务器的复制状态
- 修改应用的数据库连接,指向新的主服务器
- 如果原来的主服务器修好了,可以把它改成新的主服务器的从服务器,继续复制
当然,手动故障转移比较麻烦,而且需要时间,生产环境建议用自动故障转移工具,比如MHA、Orchestrator等,可以自动检测主服务器故障,自动提升从服务器为主,自动切换,大大提升可用性。
六、最佳实践和注意事项
最后,总结一些主从复制的最佳实践和注意事项,帮助大家用好主从复制。
1. 主从服务器版本尽量一致
主从服务器的MySQL版本最好一致,或者从服务器的版本不低于主服务器。如果版本差太多,可能会有兼容性问题,导致复制失败。
2. 所有表都要有主键
特别是用基于行的复制的时候,表一定要有主键,不然从服务器更新数据的时候需要全表扫描,性能很差,延迟会很大。而且没有主键的表,在主从切换的时候也容易出问题。
3. 从服务器设置read_only
从服务器一定要设置read_only=1,防止普通用户误写数据,导致主从数据不一致。当然,超级用户还是可以写的,所以也要注意不要在从服务器上用超级用户写数据。
4. 定期检查主从状态
要定期检查主从复制的状态,看看IO线程和SQL线程是不是正常,有没有延迟,有没有错误。可以写个监控脚本,自动检查,出问题了及时告警,不要等数据不一致很久了才发现。
5. 不要在从服务器上手动写数据
除非是特殊情况,否则不要在从服务器上手动写数据,因为这样会导致主从数据不一致,后面复制的时候很容易出错,而且很难排查。如果需要写数据,在主服务器上写,然后复制到从服务器。
6. 备份要定期做
主从复制不是备份的替代品,虽然从服务器有一份数据,但是还是要定期做物理备份或者逻辑备份,因为主从复制只能复制数据变更,如果主服务器上误删了数据,从服务器上也会被删掉。所以定期备份还是很有必要的,备份是数据安全的最后一道防线。
7. 读写分离要注意延迟
用读写分离的时候,要注意主从延迟的问题,刚写入主服务器的数据,可能还没复制到从服务器,这时候去从服务器查询,可能查不到。对于一致性要求高的场景,比如刚注册完马上登录,刚下单马上查订单,这些读操作应该走主服务器,或者等复制完成了再查。
8. 从服务器不要太多
一主多从的架构,从服务器不要太多,一般不要超过5个,因为每个从服务器都要从主服务器拉取binlog,从服务器太多了,主服务器的网络和IO压力会很大,影响主服务器的性能。如果需要更多的从服务器,可以用级联复制的方式,减轻主服务器的压力。
七、写在最后
MySQL主从复制入门指南:从零开始学习。
以上就是MySQL主从复制的入门指南,从原理、作用、类型,到具体的配置步骤、常见问题、最佳实践,都做了比较详细的介绍。希望这篇文章能帮到想学习MySQL主从复制的朋友,让大家从零开始,快速掌握主从复制的配置和使用。
MySQL主从复制是MySQL高可用架构的基础,也是每个后端开发者和运维人员必须掌握的技能。虽然现在有很多云数据库,自带主从复制、高可用、自动备份等功能,不用我们自己配置,但是了解主从复制的原理和使用,还是很有必要的,能帮助我们更好地理解数据库架构,更好地使用和优化数据库。
当然,这篇文章只是入门指南,讲的都是基础的内容,主从复制还有很多深入的内容,比如并行复制、半同步复制、GTID、多源复制、组复制等等,这些都需要大家在实际工作中继续学习和实践。技术是学无止境的,希望大家都能保持学习的热情,不断提升自己。
最后用一句话结尾:"主从复制不是万能的,但是没有主从复制是万万不能的。掌握好主从复制,给你的数据上一份保险。"
祝大家都能配置好自己的MySQL主从复制,数据库稳定运行,数据永不丢失!
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录