MySQL主从同步延迟原因与解决方案
一、MySQL数据库主从同步延迟产生的原因
MySQL的主从复制都是单线程的操作,主库对所有DDL和DML产生的日志写进binlog,由于binlog是顺序写,所以效率很高。
Slave的SQL Thread线程将主库的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是随即的,不是顺序的,成本高很多。 另一方面,由于SQL Thread也是单线程的,当主库的并发较高时,产生的DML数量超过slave的SQL Thread所能处理的速度,或者当slave中有大型query语句产生了锁等待那么延时就产生了。
常见原因:Master负载过高、Slave负载过高、网络延迟、机器性能太低、MySQL配置不合理。
二、关于DDL和DML
SQL语言共分为以下几大类:查询语言DQL,控制语言DCL,操纵语言DML,定义语言DDL。事务控制TCL
- DQL(Data QUERY Languages)语句:即数据库定义语句,用来查询SELECT子句,FROM子句,WHERE子句组成的查询块,比如:select–from–where–grouop by–having–order by–limit
- DDL(Data Definition Languages)语句:即数据库定义语句,用来创建数据库中的表、索引、视图、存储过程、触发器等,常用的语句关键字有:CREATE,ALTER,DROP,TRUNCATE,COMMENT,RENAME。增删改表的结构
- DML(Data Manipulation Language)语句:即数据操纵语句,用来查询、添加、更新、删除等,常用的语句关键字有:SELECT,INSERT,UPDATE,DELETE,MERGE,CALL,EXPLAIN PLAN,LOCK TABLE,包括通用性的增删改查。增删改表的数据
- DCL(Data Control Language)语句:即数据控制语句,用于授权/撤销数据库及其字段的权限(DCL is short name of Data Control Language which includes commands such as GRANT and mostly concerned with rights, permissions and other controls of the database system.)。常用的语句关键字有:GRANT,REVOKE。
- TCL(Transaction Control Language)语句:事务控制语句,用于控制事务,常用的语句关键字有:COMMIT,ROLLBACK,SAVEPOINT,SET TRANSACTION。
三、主从延时排查方法
通过监控 show slave status 命令输出的Seconds_Behind_Master参数的值来判断:
- NULL,表示io_thread或是sql_thread有任何一个发生故障;
- 0,该值为零,表示主从复制良好;
- 正值,表示主从已经出现延时,数字越大表示从库延迟越严重
四、解决方案
解决数据丢失的问题:
- 半同步复制
从MySQL5.5开始,MySQL已经支持半同步复制了,半同步复制介于异步复制和同步复制之间,主库在执行完事务后不立刻返回结果给客户端,需要等待至少一个从库接收到并写到relay log中才返回结果给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一个TCP/IP往返耗时的延迟。 - 主库配置sync_binlog=1,innodb_flush_log_at_trx_commit=1 sync_binlog的默认值是0,MySQL不会将binlog同步到磁盘,其值表示每写多少binlog同步一次磁盘。
innodb_flush_log_at_trx_commit为1表示每一次事务提交或事务外的指令都需要把日志flush到磁盘。
注意:将以上两个值同时设置为1时,写入性能会受到一定限制,只有对数据安全性要求很高的场景才建议使用,比如涉及到钱的订单支付业务,而且系统I/O能力必须可以支撑!
3.1 解决从库复制延迟的问题:
- 架构方面
- 业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。
- 单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。
- 服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力。
- 不同业务的mysql物理上放在不同机器,分散压力。
- 使用比主库更好的硬件设备作为slave,mysql压力小,延迟自然会变小。
- 硬件方面
- 采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。
- 存储用ssd或者盘阵或者san,提升随机写的性能。
- 主从间保证处在同一个交换机下面,并且是万兆环境。
总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。
- mysql主从同步加速
- sync_binlog在slave端设置为0
- –logs-slave-updates 从服务器从主服务器接收到的更新不记入它的二进制日志。
- 直接禁用slave端的binlog
- .slave端,如果使用的存储引擎是innodb,innodb_flush_log_at_trx_commit =2
- 从文件系统本身属性角度优化
master端修改linux、Unix文件系统中文件的etime属性, 由于每当读文件时OS都会将读取操作发生的时间回写到磁盘上,对于读操作频繁的数据库文件来说这是没必要的,只会增加磁盘系统的负担影响I/O性能。可以通过设置文件系统的mount属性,组织操作系统写atime信息,在linux上的操作为:打开/etc/fstab,加上noatime参数/dev/sdb1 /data reiserfs noatime 1 2然后重新mount文件系统#mount -oremount /data - 同步参数调整主库是写,对数据安全性较高,比如sync_binlog=1,
innodb_flush_log_at_trx_commit = 1 之类的设置是需要的而slave则不需要这么高的数据安全,完全可以讲sync_binlog设置为0或者关闭binlog,innodb_flushlog也可以设置为0来提高sql的执行效率
3.2 MySql数据库从库同步其他问题及解决方案
- mysql主从复制存在的问题:
- 主库宕机后,数据可能丢失
- 从库只有一个sql Thread,主库写压力大,复制很可能延时
- 解决方法:
- 半同步复制—解决数据丢失的问题
- 并行复制----解决从库复制延迟的问题
- 半同步复制mysql semi-sync(半同步复制)半同步复制:
- 5.5集成到mysql,以插件的形式存在,需要单独安装
- 确保事务提交后binlog至少传输到一个从库
- 不保证从库应用完这个事务的binlog
- 性能有一定的降低,响应时间会更长
- 网络异常或从库宕机,卡主主库,直到超时或从库恢复
- 主从复制–异步复制原理、半同步复制和并行复制原理比较