有个客户问我:我们每天凌晨做一次全量备份,白天数据要是出事怎么办?这个问题问到了点子上。全量备份解决的是“昨天还在”的问题,而主从复制解决的是“每秒都在”的问题。它本质上是一种实时数据同步机制,主库的每一次变更都会几乎同步到从库。
主从复制的基本原理
MySQL主从复制依赖三个线程协作:主库的Binlog Dump线程负责读取binlog并发送给从库,从库的I/O线程负责接收并写入relay log,从库的SQL线程负责回放relay log中的事件。三个线程任何一个断了,复制就会停止。
理解这个链路对排障很重要。复制延迟了,先看I/O线程是不是在追日志;数据不一致了,先看SQL线程是不是报错停了。
配置步骤:从零搭建主从同步
第一步,主库配置。在my.cnf中设置server-id=1、log_bin=mysql-bin、binlog_format=ROW,重启MySQL后创建复制账号:CREATE USER 'repl'@'%' IDENTIFIED BY '密码'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
第二步,获取主库当前binlog位置。执行SHOW MASTER STATUS;记录下File和Position的值,后面从库配置要用。
第三步,把主库现有数据导出并导入从库。用mysqldump --single-transaction --master-data=2导出,这个参数会自动在导出文件中注释记录binlog位置,省去手动查找。
第四步,从库配置。设置不同的server-id,然后执行CHANGE MASTER TO MASTER_HOST='主库IP', MASTER_USER='repl', MASTER_PASSWORD='密码', MASTER_LOG_FILE='记录的File', MASTER_LOG_POS=记录的Position;,最后START SLAVE;。
第五步,验证。在从库执行SHOW SLAVE STATUS\G,确认Slave_IO_Running和Slave_SQL_Running都是Yes。
常见坑和应对方法
最大的坑是复制中断后不知道怎么修。如果SQL线程报主键冲突错误,可以用SET GLOBAL sql_slave_skip_counter=1;跳过这条事务,但治标不治本。更稳妥的做法是对比主从数据差异,用pt-table-sync工具修复不一致的表。
另一个坑是大事务导致延迟。一个事务包含几百万行更新,从库回放时会严重滞后。把大事务拆成小批次执行,能有效控制复制延迟。
主从复制搭好之后,从库本身就是一份实时备份。再配合定期全量备份和数据迁移备份策略,你的数据库安全等级会上一个台阶。