MySQL数据库主从同步延迟原理
要说延时原理得从mysql的数据库主从复制原理说起mysql的主从复制都是单线程的操作
主库对所有DDL和DML产生binlogbinlog是顺序写所以效率很高slave的Slave_IO_Running线程到主库取日志效率很比较高下一步问题来了slave的Slave_SQL_Running线程将主库的DDL和DML操作在slave实施DML和DDL的IO操作是随即的不是顺序的成本高很多还可能可slave上的其他查询产生lock争用由于Slave_SQL_Running也是单线程的所以一个DDL卡主了需要执行分钟那么所有之后的DDL会等待这个DDL执行完才会继续执行这就导致了延时有朋友会问主库上那个相同的DDL也需要执行分为什么slave会延时?答案是master可以并发Slave_SQL_Running线程却不可以
MySQL数据库主从同步延迟是怎么产生的
当主库的TPS并发较高时产生的DDL数量超过slave一个sql线程所能承受的范围那么延时就产生了当然还有就是可能与slave的大型query语句产生了锁等待
MySQL数据库主从同步延迟解决方案
丁奇的transefer是一个不错的方案不过一般公司受限于对mysql的代码修改能力的限制和对mysql的掌控能力还是不太适合
最简单的减少slave同步延时的方案就是在架构上做优化尽量让主库的DDL快速执行还有就是主库是写对数据安全性较高比如sync_binlog=innodb_flush_log_at_trx_commit = 之类的设置而slave则不需要这么高的数据安全完全可以讲sync_binlog设置为或者关闭binloginnodb_flushlog也可以设置为来提高sql的执行效率另外就是使用比主库更好的硬件设备作为slave
mysql已经支持了多线程的主从复制原理和丁奇的类似丁奇的是以表做多线程oracle使用的是以数据库(schema)为单位做多线程不同的库可以使用不同的复制线程
sync_binlog= o
This makes MySQL synchronize the binary logs contents to disk each time it commits a transaction
默认情况下并不是每次写入时都将binlog与硬盘同步因此如果操作系统或机器(不仅仅是MySQL服务器)崩溃有可能binlog中最后的语句丢 失了要想防止这种情况你可以使用sync_binlog全局变量(是最安全的值但也是最慢的)使binlog在每N次binlog写入后与硬盘 同步即使sync_binlog设置为出现崩溃时也有可能表内容和binlog内容之间存在不一致性如果使用InnoDB表MySQL服务器 处理COMMIT语句它将整个事务写入binlog并将事务提交到InnoDB中如果在两次操作之间出现崩溃重启时事务被InnoDB回滚但仍 然存在binlog中可以用innodbsafebinlog选项来增加InnoDB表内容和binlog之间的一致性(注释在MySQL 中不需要innodbsafebinlog;由于引入了XA事务支持该选项作废了)该选项可以提供更大程度的安全使每个事务的 binlog(sync_binlog =)和(默认情况为真)InnoDB日志与硬盘同步该选项的效果是崩溃后重启时在滚回事务后MySQL服务器从binlog剪切回滚的 InnoDB事务这样可以确保binlog反馈InnoDB表的确切数据等并使从服务器保持与主服务器保持同步(不接收 回滚的语句)
innodb_flush_log_at_trx_commit (这个很管用)
抱怨Innodb比MyISAM慢 倍?那么你大概是忘了调整这个值默认值的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘这是很费时的特别是使用电 池供电缓存(Battery backed up cache)时设成对于很多运用特别是从MyISAM表转过来的是可以的它的意思是不写入硬盘而是写入系统缓存日志仍然会每秒flush到硬 盘所以你一般不会丢失超过秒的更新设成会更快一点但安全方面比较差即使MySQL挂了也可能会丢失事务的数据而值只会在整个操作系统 挂了时才可能丢数据