当前位置: 首页 > 科技观察

mysql主从同步呢

时间:2023-03-13 18:15:59 科技观察

1.前言对于mysql主从同步,相信大家都不陌生。当读写访问达到一定的瓶颈时,数据库的读写效率会突然下降,甚至不可用;为了解决这类问题,通常使用mysql集群。当主库宕机时,集群会自动升级一个从库为主库,继续对外提供服务;那么主库和从库之间的数据是如何同步的呢?本文对MySQL5.7版本进行分析如下,跟随笔者一起探讨mysql主从是如何同步的。2、MySQL主从复制的原理为了减少主库的压力,在系统应用层面应该做读写分离。写操作到主库,读操作到从库。下图是MySQL官网给??出的主从复制示意图,从图中可以很容易理解读写分离和主从同步的过程,分散了数据库的访问压力,提高了整个系统的性能和可用性,降低大访问量导致数据库宕机的故障率。3、binlog介绍MySQL主从同步是基于binlog文件的主从复制。为了更好的理解主从同步过程,这里简单介绍下binlog日志文件。binlog日志用于记录所有更新数据或有潜在更新数据的语句(例如,不匹配任何行的DELETE)。语句存储为“事件”,它描述数据的变化,并以二进制形式存储在磁盘上。我们可以通过mysql提供的查看工具mysqlbinlog查看文件内容,比如mysqlbinlogmysql-bin.00001|more,这里注意binlog文件的后缀名00001,binlog文件的大小和数量会不断增加,当MySQL停止或者重启时,会生成一个新的binlog文件,后缀名会根据序号,如mysql-bin.00002、mysql-bin.00003,当binlog文件的大小超过max_binlog_size系统变量配置时,也会生成一个新的binlog文件。(1)binlog日志格式(1)statement:记录每条变化数据的sql;优点:binlog文件小,节省I/O,性能高。缺点:并不是所有的数据变化都会写入binlog文件,尤其是使用MySQL中的一些特殊函数(如LOAD_FILE()、UUID()等)和一些不确定的语句操作,导致主从数据无法写入重复的问题。(2)row:不记录sql,只记录每一行数据的变化详情优点:详细记录了每一行数据的变化细节,也意味着不会出现无法复制的问题由于使用某些特殊功能或其他情况。缺点:由于行格式记录了每一行数据的变化细节,会产生大量的binlog日志内容,性能较差,主从同步延迟的概率会增加。(3)Mixed:一般语句修改使用statment格式保存binlog。比如有些功能,语句无法完成主从复制操作,采用行格式保存binlog。MySQL会根据执行的每个特定SQL语句来处理记录。日志形式,即Statement和Row二选一。(2)Binlog日志内容mysqlbinlog命令查看的内容如下:按事件类型查看的Binlog内容:(3)Binlog事件类型MySQLbinlog中记录的所有操作其实都有对应的事件类型,比如STATEMENT格式的DML操作对应QUERY_EVENT类型,ROW格式的DML操作对应ROWS_EVENT类型。如果想了解更多,请参考官方文档。binlog日志的内容这里不再赘述。简单的介绍是为了更好的理解主从复制的细节,下面进入正题。4、MySQL主从复制原理MySQL主从复制需要三个线程,master(binlogdump线程),slave(I/O线程,SQL线程)。master(1)binlogdump线程:当主库有数据更新时,主库会将更新的事件类型按照设置的binlog格式写入主库的binlog文件中。这时主库会创建一个日志转储线程通知从库有数据更新。当I/O线程请求日志内容时,会同时将binlog名称和当前更新位置发送给从I/O线程。slave(2)I/O线程:该线程会连接到master,向logdump线程请求一份指定binlog文件所在位置的副本,并将请求的binlog保存到本地relaylog。relaylog和binloglog一样,也是记录数据更新事件。它还以增加后缀名的方式生成多个中继日志(host_name-relay-bin.000001)文件。从机将使用一个索引文件(host_name-relay-bin.index)来跟踪当前正在使用的中继日志文件。(3)SQL线程:线程检测到relaylog有更新后,会在本地读取并执行redo操作,在本地重新执行主库发生的事件,保证主从数据的同步。另外,如果一个relaylog文件中的所有事件都执行完了,SQL线程会自动删除relaylog文件。下面是整个复制过程的示意图:4.主从同步延迟MySQL的主从复制是单线程操作。主库为所有的DDL和DML生成binlog。binlog是顺序写入的,所以效率很高。从库的I/O线程从主库取日志,效率更高。而从库的SQL线程在从库上实现了主库的DDL和DML操作。DML和DDL的IO操作是随机的,不是顺序的,成本要高很多。也可能存在由从站上的其他查询引起的锁争用。由于SQL也是单线程的,一个DDL就卡住了,需要执行很长时间。很长一段时间,后续的DDL线程会等待DDL执行完再执行,从而导致延迟。主库TPS并发高时,DDL产生量超过从库一个sql线程所能承受的范围,出现延迟。另外还有可能是slave的大查询语句导致的锁等待。既然主从同步延迟是客观存在的,那么我们只能从自己的架构上去设计,尽量让主库的DDL执行的快。下面列出几种常见的解决方案:业务持久层的实现采用分库架构,mysql服务可以并行扩展,分散压力。服务的基础架构在业务和mysql之间增加了一个memcache或者Redis缓存层。降低mysql的读压力;使用比主库更好的硬件设备作为从库;slave端sync_binlog设置为0;--logs-slave-updates从服务器从主服务器接收到的更新不记录在它的二进制日志中。禁用从属二进制日志