公司动态
MariaDB主从复制实战:从原理到高可用架构部署
1. 项目概述为什么我们需要MariaDB主从配置如果你负责的线上业务数据库压力越来越大单台服务器开始出现性能瓶颈或者你开始为数据安全与业务连续性感到焦虑那么“主从复制”就是你必须要掌握的核心技能。这不是一个炫技的配置而是一个生产环境数据库架构的基石。简单来说主从复制就是将一台MariaDB服务器主库上的数据实时地同步到另一台或多台服务器从库上。主库负责处理所有的写操作增、删、改而从库则主要承担读操作查询的压力。我经历过不少从单点数据库到主从架构的迁移最直接的感受就是业务高峰期查询慢的报警短信变少了DBA的睡眠质量变高了。这背后的价值非常具体首先是读写分离将密集的读请求分流到从库极大减轻主库负担提升整体吞吐量。其次是数据备份与高可用从库本身就是一份实时热备一旦主库宕机可以快速切换从库顶上极大缩短业务中断时间。最后是数据分析与报表可以在从库上运行那些耗时很长的统计查询而完全不影响主库的在线交易性能。MariaDB作为MySQL的一个重要分支在性能和功能上都有诸多增强其主从复制机制成熟稳定。今天我就以一个老DBA的视角带你从零开始手把手搭建一套MariaDB主从复制环境并深入那些官方文档不会细说的“坑”与技巧让你不仅能配通更能配得稳、配得明白。2. 环境准备与规划兵马未动粮草先行在动手敲命令之前合理的规划能避免后续无数麻烦。主从配置不是简单的安装复制它涉及到网络、资源、版本和架构的统筹。2.1 服务器与网络规划你需要至少两台服务器虚拟机或物理机均可我们分别命名为master-server主库和slave-server从库。IP与主机名确保两台服务器有固定的IP地址并且可以通过主机名或IP相互ping通。在生产环境中强烈建议在/etc/hosts文件中做好解析或者使用内部DNS。# 在主库和从库上都执行添加对方的主机名解析 192.168.1.100 master-server 192.168.1.101 slave-server防火墙与端口MariaDB默认使用3306端口。你需要在两台服务器的防火墙中开放此端口允许对方访问。如果使用firewalld如CentOS/RHELsudo firewall-cmd --permanent --add-port3306/tcp sudo firewall-cmd --reload如果使用ufw如Ubuntu/Debiansudo ufw allow from 对方IP to any port 3306 sudo ufw reload时间同步主从服务器之间的系统时间必须保持基本一致否则可能导致复制延迟计算不准甚至数据问题。务必配置NTP服务进行时间同步。# 以Ubuntu为例 sudo apt install ntpdate -y sudo ntpdate time.windows.com # 或使用你的本地NTP服务器 # 更推荐使用chrony或systemd-timesyncd进行持续同步2.2 MariaDB安装与基础配置在两台服务器上安装相同主要版本的MariaDB。例如都安装MariaDB 10.6。不同大版本间的复制可能存在问题小版本也尽量一致。安装以Ubuntu 20.04为例通过官方仓库安装。sudo apt update sudo apt install mariadb-server mariadb-client -y安全初始化安装后运行sudo mysql_secure_installation脚本设置root密码、移除匿名用户、禁止root远程登录等。这一步对主库和从库都至关重要。关键配置文件my.cnf调整这是主从配置的核心。我们需要分别配置主库和从库的my.cnf通常位于/etc/mysql/mariadb.conf.d/50-server.cnf或/etc/my.cnf。注意修改配置文件前务必先备份任何配置错误都可能导致数据库无法启动。3. 主库Master配置详解开启数据源头主库的配置核心是开启二进制日志Binary Log并创建一个专用于复制的用户。3.1 主库配置文件修改编辑主库的my.cnf文件在[mysqld]部分添加或修改以下参数[mysqld] # 服务器唯一ID主从库必须不同通常主库设为1 server-id 1 # 启用二进制日志这是复制的基石。日志文件前缀为mysql-bin log-bin /var/log/mysql/mysql-bin.log # 设置二进制日志格式为ROW这是最安全、最推荐的格式能保证主从数据绝对一致 binlog-format ROW # 指定需要复制的数据库名如果多个则写多行。这里以app_db为例 binlog-do-db app_db # 可选指定不需要复制的数据库如系统库。通常忽略mysql库 binlog-ignore-db mysql # 设置二进制日志过期天数避免磁盘被占满 expire_logs_days 7 # 确保事务在从库上也是以ROW格式记录用于级联复制等高级场景 binlog_row_image full参数解读server-id复制拓扑中每个节点的“身份证”必须全局唯一。log-bin二进制日志记录了所有对数据库的修改事件DDL和DML。从库通过读取这个日志来重放操作。binlog-formatROW这是关键。STATEMENT格式记录SQL语句可能在主从数据不一致如使用了UUID()、NOW()函数。ROW格式记录每行数据的变化更安全可靠。binlog-do-db白名单机制只复制指定的库。如果所有库都复制可以注释掉此参数。修改完成后重启MariaDB服务使配置生效sudo systemctl restart mariadb3.2 创建复制专用账户并授权出于安全考虑我们不应该让从库直接用root账号连接主库。需要创建一个仅有复制权限的账户。登录主库的MySQL命令行sudo mysql -u root -p执行以下SQL语句-- 创建一个用户名为repl允许从slave-server的IP地址登录的用户密码设为StrongPassword123! CREATE USER replslave-server IDENTIFIED BY StrongPassword123!; -- 授予该用户复制相关的权限 GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO replslave-server; -- 刷新权限 FLUSH PRIVILEGES;实操心得这里的slave-server是主机名如果你配置了hosts解析就用主机名否则请使用从库的IP地址如repl192.168.1.101。权限REPLICATION SLAVE是从库连接主库所必需的REPLICATION CLIENT方便用于监控复制状态。3.3 锁定主库并获取初始状态为了确保从库从一个一致性的起点开始复制我们需要暂时阻止主库的写操作并记录下当前的二进制日志坐标文件名和位置。在主库命令行中刷新所有表并加读锁FLUSH TABLES WITH READ LOCK;这个命令会阻止新的写操作但读操作仍可进行。非常重要另开一个SSH连接到主库使用mysql -u root -p再次登录。因为上一步的锁会在当前会话断开时释放。在新会话中获取主库状态SHOW MASTER STATUS;你会看到类似下面的输出务必记下File和Position的值稍后在从库配置时需要用到。------------------------------------------------------------ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | ------------------------------------------------------------ | mysql-bin.000003 | 345 | app_db | mysql | ------------------------------------------------------------如果之前主库已有数据现在需要将数据导出并传输到从库。在第二个SSH会话中执行# 导出数据忽略系统表 mysqldump -u root -p --databases app_db --single-transaction --master-data2 master_data.sql--single-transaction在事务中导出确保数据一致性且不会长时间锁表对InnoDB有效。--master-data2会在导出的SQL文件中以注释形式包含CHANGE MASTER TO语句其中就有File和Position信息可以作为备份。数据导出完成后回到第一个SSH会话执行了FLUSH TABLES WITH READ LOCK的那个释放锁UNLOCK TABLES;将导出的master_data.sql文件传输到从库服务器scp master_data.sql userslave-server:/tmp/4. 从库Slave配置与数据同步建立复制链路现在我们转向从库服务器进行操作。4.1 从库配置文件修改编辑从库的my.cnf文件在[mysqld]部分添加[mysqld] # 服务器唯一ID必须与主库不同 server-id 2 # 从库一般不需要开启二进制日志除非它要作为其他从库的主库级联复制 # relay-log /var/log/mysql/mysql-relay-bin.log # 指定需要复制的数据库可选通常与主库对应 replicate-do-db app_db # 跳过复制错误生产环境慎用仅用于测试或特定情况 # slave-skip-errors all重启从库的MariaDB服务sudo systemctl restart mariadb4.2 导入初始数据并配置复制在从库上导入从主库传输过来的数据sudo mysql -u root -p /tmp/master_data.sql登录从库的MySQL命令行配置复制源sudo mysql -u root -p-- 停止从库复制线程如果是新库本应就是停止的 STOP SLAVE; -- 配置主库连接信息使用你在主库查到的 File 和 Position -- MASTER_HOST: 主库IP或主机名 -- MASTER_USER/MASTER_PASSWORD: 主库创建的复制账号 -- MASTER_LOG_FILE / MASTER_LOG_POS: 主库状态中记录的值 CHANGE MASTER TO MASTER_HOSTmaster-server, MASTER_USERrepl, MASTER_PASSWORDStrongPassword123!, MASTER_LOG_FILEmysql-bin.000003, -- 替换为你的文件名 MASTER_LOG_POS345; -- 替换为你的位置 -- 启动从库复制线程 START SLAVE;4.3 检查复制状态配置完成后使用以下命令检查从库的复制状态SHOW SLAVE STATUS\G使用\G代替分号可以让结果以垂直格式显示更易读。你需要重点关注以下几行Slave_IO_State: 显示IO线程的状态正常应为Waiting for master to send event。Slave_IO_Running:必须为Yes。表示IO线程负责从主库拉取日志正在运行。Slave_SQL_Running:必须为Yes。表示SQL线程负责重放日志中的事件正在运行。Seconds_Behind_Master: 复制延迟秒数。0表示没有延迟。这个值在初始同步或主库有大量写入时可能会较大稍后会追平。Last_IO_Error/Last_SQL_Error: 显示最近的错误信息。如果复制中断这里会有详细报错。如果Slave_IO_Running和Slave_SQL_Running都是Yes且Seconds_Behind_Master逐渐变为0那么恭喜你主从复制已经成功建立5. 深入原理与高级配置知其所以然仅仅搭建成功还不够理解其工作原理和掌握高级配置才能应对复杂场景。5.1 复制线程与流程拆解MariaDB主从复制是异步的依赖于三个线程主库 Binlog Dump Thread当有从库连接时主库会为每个连接的从库创建一个Binlog Dump线程负责读取二进制日志事件并发送给从库的IO线程。从库 I/O Thread从库的IO线程连接到主库接收主库Binlog Dump线程发来的事件并将其写入本地的中继日志Relay Log。从库 SQL Thread从库的SQL线程读取中继日志中的事件并在从库上重放执行从而实现数据同步。流程主库事务提交 - 写入Binlog - 主库Binlog Dump线程读取 - 发送至从库IO线程 - 从库IO线程写入Relay Log - 从库SQL线程读取Relay Log并执行 - 从库数据更新。5.2 二进制日志格式binlog-format的选择这是复制稳定性的关键。STATEMENT (SBR): 记录SQL语句本身。优点日志量小。缺点对于使用非确定性函数如RAND(),UUID(),NOW()的语句在主从库上执行结果可能不同导致数据不一致。ROW (RBR): 记录每行数据如何被修改。优点数据一致性最强能保证主从绝对一致。缺点日志量可能非常大例如一条UPDATE语句更新了100万行会记录100万行变化。MIXED (MBR): 混合模式。通常使用STATEMENT但在可能引起不一致时自动切换到ROW。这是一个折中方案。生产环境强烈推荐使用ROW格式。虽然日志量大但数据安全是第一位的。可以通过设置binlog_row_image MINIMAL只记录被修改的列和唯一标识列来适当减少日志体积。5.3 半同步复制与并行复制半同步复制默认的复制是异步的主库提交事务后不等从库确认就返回给客户端。半同步复制要求主库提交事务时至少有一个从库已收到并写入中继日志后才返回增强了数据安全性但会轻微增加主库的响应延迟。# 在主库安装插件并启用 INSTALL PLUGIN rpl_semi_sync_master SONAME semisync_master.so; SET GLOBAL rpl_semi_sync_master_enabled ON; # 在从库安装插件并启用 INSTALL PLUGIN rpl_semi_sync_slave SONAME semisync_slave.so; SET GLOBAL rpl_semi_sync_slave_enabled ON; # 从库需要重启IO线程 STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;并行复制默认从库的SQL线程是单线程重放事件在主库写入压力大时从库容易产生延迟。并行复制允许SQL线程并行执行多个事务大幅提升从库重放速度。在MariaDB 10.0中可以通过设置slave_parallel_threads和slave_parallel_mode来启用。# 在从库my.cnf中 [mysqld] slave_parallel_threads 4 # 根据CPU核心数调整 slave_parallel_mode optimistic6. 监控、维护与故障排查实战配置好不是终点日常监控和问题处理才是DBA的日常工作。6.1 关键监控指标与命令复制状态SHOW SLAVE STATUS\G是每日必查命令。复制延迟关注Seconds_Behind_Master。持续较高的延迟需要分析原因主库写入过快、从库性能瓶颈、网络问题。二进制日志空间定期检查主库二进制日志是否按expire_logs_days设置自动清理。SHOW BINARY LOGS;查看日志列表。从库一致性检查可以使用pt-table-checksumPercona Toolkit工具来定期检查主从数据是否一致。6.2 常见故障场景与处理实录场景一从库SQL线程报错停止Slave_SQL_Running: No典型错误在从库上执行了写操作或者主从数据因故不一致导致执行中继日志中的事件时发生主键冲突、数据不存在等错误。查看错误SHOW SLAVE STATUS\G中的Last_SQL_Error字段。经典处理方案跳过指定错误-- 先停止从库 STOP SLAVE; -- 设置全局变量跳过接下来的1个错误谨慎使用确保跳过的错误不会导致数据逻辑错误 SET GLOBAL sql_slave_skip_counter 1; -- 重新启动从库 START SLAVE; -- 再次检查状态 SHOW SLAVE STATUS\G踩坑提醒sql_slave_skip_counter是跳过事件而不是忽略错误号。如果错误持续发生如重复插入同一条数据可能需要先手动在从库上处理掉冲突数据再跳过错误。最根本的解决方法是重建一致性快照。场景二主库二进制日志被误删除从库请求的日志文件不存在错误信息Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: Could not find first log file name in binary log index file解决方案这通常意味着从库落后太多而主库的过期日志已被清理。此时需要重建从库。在主库用mysqldump重新导出全量数据使用--master-data。在从库停止复制清空数据重新导入全量数据。使用新的File和Position重新执行CHANGE MASTER TO。场景三网络中断后IO线程无法连接主库错误信息Last_IO_Error: error reconnecting to master...解决方案检查网络连通性、主库防火墙规则、复制用户权限是否正常。确认无误后重启从库IO线程STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;6.3 主从切换演练手动为了应对主库宕机需要定期演练主从切换。确认主库故障尝试连接主库确认无法恢复。选择并提升从库选择一个数据最接近的从库Seconds_Behind_Master最小。在该从库上执行STOP SLAVE;停止复制。执行RESET SLAVE ALL;谨慎这会清除所有复制配置信息使其脱离复制关系成为一个独立的主库。应用端切换将应用程序的数据库连接地址从原主库IP修改为新主库IP。其他从库指向新主库如果有多从架构需要让其他从库指向新的主库。在新主库上创建新的复制账户在其他从库上重新执行CHANGE MASTER TO命令指向新主库的日志坐标需要在新主库上执行SHOW MASTER STATUS;获取。核心经验主从切换的难点不在于技术命令而在于流程标准化和演练熟练度。一定要有书面化的应急预案并定期在测试环境演练。自动化切换工具如MHA, Orchestrator可以降低操作风险但理解手动步骤是基础。7. 性能调优与安全加固建议一个稳健的主从环境离不开调优和安全。7.1 性能调优要点从库硬件从库的硬件配置尤其是CPU、磁盘IOPS不应低于主库特别是当从库承担大量读请求时。从库索引从库上可以为查询频繁的读负载创建额外的索引这不会影响主库但能极大提升从库的查询性能。网络优化主从之间的网络延迟直接影响Seconds_Behind_Master。确保它们在同一机房或通过高质量内网连接。并行复制如前所述务必启用并合理配置slave_parallel_threads。中继日志管理确保relay_log_space_limit设置合理避免中继日志写满磁盘。7.2 安全加固措施最小权限原则复制用户repl只授予REPLICATION SLAVE和REPLICATION CLIENT权限且限定来源IP。SSL加密连接如果主从跨公网或不可信网络务必配置SSL加密复制链路防止数据在传输中被窃听。-- 在主从库上配置SSL然后在CHANGE MASTER时加入参数 CHANGE MASTER TO ..., MASTER_SSL1, MASTER_SSL_CA/path/to/ca.pem, MASTER_SSL_CERT/path/to/client-cert.pem, MASTER_SSL_KEY/path/to/client-key.pem;定期审计定期检查SHOW PROCESSLIST查看是否有异常的复制连接。搭建MariaDB主从复制从步骤上看并不复杂但每一个参数背后都有其设计考量每一次故障都可能由不同原因引发。我的体会是把主从复制配通只是第一步真正考验人的是在长期运行中如何保持其稳定、高效并能在故障发生时快速、准确地恢复。建议你在测试环境中反复演练整个搭建、监控、故障模拟和切换流程把这些命令和思路变成肌肉记忆。当生产环境真的出现问题时你才能有条不紊心里不慌。