现在我们的应用基本都往高性能的方向发展,各种语言都开始推出一些多进程和分布式的框架,其目的就是为了能够做到一个高性能的应用。包括会使用各种MQ和缓存的中间件,其实使用这些中间件的最终目的都是为了能够缓解数据库的压力,数据库是所有应用中的最后一环。因此提高数据库的性能也是必要的。主从复制解决数据库的访问压力,降低单个服务器的IO访问频率。
MySQL主从复制是将一个Mysql数据库服务器中的数据复制到多个从服务器中,用从服务器分担主服务器的读取频率。一个主服务器可以有多个从服务器,一个从服务器只能有一个主服务器即一主一从或一主多从的结构,但是在mysql5.7已经可以支持多主一从。
从上图可以看出,mysql主从复制涉及到3个线程(主服务器的log dump thread,从服务器的IOthread 和SQL thread )和2个日志(主服务器的binlog和从服务器的relaylog)。
log dump thread
从服务器连接主节点时,主服务器会为每个从服务器创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时会对主服务器上的binlog加锁,当读取完成后锁则会释放。
IO thread
从服务器的I/O线程是用来连接主服务器,I/O线程读取到主节点binlog dump 进程发来的bin log内容并保存在从服务器的relaylog中。
SQL thread
SQL线程负责读取relaylog中的内容并解析重做到从库中。
主从复制的过程
1. 客户端发起数据更新时,主服务器在事务prepare时讲数据更新写入到binlog日志中。
2. 从服务器会通过IO线程通过主服务器的log dump线程读取到的binlog内容(以事件的方式返回)写入到从服务器的relaylog中。
3. 从服务器的SQL线程读取到relay log的事件进行重做到从库中。从数据库的数据则复制完成。
主库更新数据写入到binlog日志后,主库事务正常提交完成。从库会轮询查看主库的binlog事件,当binlog存在事件变化时则会执行复制操作。从库的复制和主库之间是异步执行的。
mysql5.5之前都是异步复制从mysql5.5开始才支持半同步复制,默认配置下是关闭的需要人工开启。
半同步复制是主库在提交后,执行事务提交的线程将一直等待,直到至少有一个半同步从库确认已将接收到所有事件中继日志(relay log)并刷新到磁盘后,才对接收到事务的事件进行确认。
注意:
主库和从库都要启用半同步复制才会进行半同步复制功能,否则主库会还原为默认的异步复制。
当主库等待超时时,也会还原为默认的异步复制。当至少有一个从库赶上时,主库会恢复到半同步复制。
MySQL5.6的并行复制
MySQL5.6的并行复制只是基于SCHEMA的并行复制。不同SCHEMA之间的复制是并行的不受影响。从库会根据不同的SCHEMA开启不同的SQL线程进行replay操作,如果只有一个数据库则并行复制就没有意义。开启并行复制需要设置参数 slave_parallel_works 数值代表开启SQL线程的数量。
MySQL5.7的并行复制
MySQL5.7对并行复制进行了升级,将并行复制的颗粒度最小化到一个事务组。它是基于组提交的并行复制MTS(enhanced multi-threaded slave)。需要设置参数 slave_parallel_type 为LOGICAL_CLOCK。
MySQL的主从复制主要是通过获取主库的binlog到从库的replaylog中然后再重做到从库中。做主从时主库和从库最好是版本一致,如果版本不一致可能出现数据同步失败的问题。如果是对时效性不强的场景下可以使用异步复制,半同步复制由于需要等待从库replaylog写入确认因此会有一定的性能问题。