MySQL Replication(基于官方文档5.6)

254 阅读6分钟

MySQL Replication(主从复制)使数据可以从一台MySQL数据库服务器(主服务器)复制到一台或多台MySQL数据库服务器(从服务器)。默认情况下,复制是异步的,因此从属服务器不需要永久连接就可以从主服务器接收更新。这意味着更新可以通过长连接进行,甚至可以通过临时或间歇连接(例如拨号服务)进行。根据配置,您可以复制数据库中的所有数据库,选定的数据库甚至选定的表。

MySQL中复制的优点包括:

  • 横向扩展解决方案(读写分离)-在多个从站之间分配负载以提高性能。在这种环境下,所有写入和更新都必须在主服务器上进行。但是,读取可能发生在一个或多个从属上。该模型可以提高写入性能(因为主机专用于更新),同时可以在越来越多的从机上显着提高读取速度。(笔者:通过主从实现读写分离)

  • 数据安全性-因为数据被复制到从服务器,并且从服务器可以暂停复制过程,所以可以在从服务器上运行备份服务而不会破坏相应的主数据。

  • 分析-可以在主服务器上创建实时数据,而信息分析可以在从服务器上进行,而不会影响主服务器的性能。(笔者的线上也有这样的案例,北京机房两个实例单间主从关系,因为无法修改源代码实现双写,所以考虑采用了主从结构在从节点进行数据分析)

  • 远程数据分发-如果别人希望使用您的主要数据副本,则可以使用复制来创建数据的本地副本以供使用,而无需永久访问主数据库。

MySQL种的复制功能支持单向异步复制,异步复制就是一台服务器作为主服务器,而一台或者多台服务器作为从服务器,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理。这与NDB CLUSTER的特性同步复制相反,在MySQL5.6种,除了内置的异步复制外,还支持半同步复制。半同步复制就是当事务提交之后,并不是立刻返回给客户端,而是先确保至少一个从库接受到事件并且写入到relay log里面去。除此之外,还有全同步,也就是主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。

详情关于半同步复制可以看以下链接: 半同步复制

MySQL根据binlog的文件内容去实现复制的,所以binlog文件的内容很大情况下决定同步的格式。众所周知,binlog的格式主要是由两种,Row和Statement(MIXED主要还是以Statement为主,特殊情况下会用到Row)。所以衍生了两种复制方式,基于语句的复制和基于行的复制。

MySQL 5.6.5及更高版本支持基于全局事务标识符 (GTID)的事务复制 。使用这种类型的复制时,不必直接使用日志文件或这些文件中的位置,这大大简化了许多常见的复制任务。因为使用GTID进行复制完全是事务性的,所以只要在主服务器上提交的所有事务也都已应用到从服务器上,就可以保证主服务器和从服务器之间的一致性。

在MySQL的从库需要设置不同的server_id,根据MySQL的设计,主库和从库通过事件机制进行连接和同步,当新的连接到来时,如果发现server-id相同,主库会断开之前的连接并重新注册新连接。当A库连接上主库时,此时B库连接到来,会断开A库连接,A库再进行重连,周而复始导致大量异常信息。

当主库和从库的server_id设置为不同的时候,备库会跳过所有主库同步的数据,导致主从数据的不一致。

1、复制格式

1.1、binlog的格式为statement

基于语句的复制的优点在于写入binlog的数据很少,所需要的日志磁盘空间也会大大减少,这也意味着可以快速的进行数据恢复和复制,任何更改的语句都会被完整的记录到binlog文件内。 当让,statement的格式也不是没有缺点,任何不确定的行为难以被复制,例如UUID()函数就无法准确的复制到从库里去。 使用基于statement的复制语句无法正确复制时会提示告警信息
[Warning] Statement is not safe to log in statement format.

其他的还有

  • INSERT ... SELECT 与基于行的复制相比,需要更多的行级锁。
  • UPDATE 比起Row格式的在需要进行表扫描的时候可能需要锁定更多的行(当后面的WHERE语句没有添加索引的时候)
  • 对于InnoDB:使用AUTO_INCREMENT的INSERT语句会阻塞其他无冲突的INSERT 语句。
  • 主库和从库的表结构必须一样。

1.2、binlog的格式为row

基于行的复制的优点在于binlog时准确记录每个记录修改前的数据和修改后的数据,这是最安全的复制形式。大多数基于binlog格式的复制,内容格式都是采用和MySQL的Row格式。除此之外,Row还有在操作以下语句时,在主库会使用比较少的行锁,因而支持更高的并发
  • INSERT ... SELECT
  • 带有AUTO_INCREMENT的INSERT
  • UPDATE 和 DELETE带有WHERE条件却无法使用索引的情况
  • 同时,从库执行INSERT、UPDATE和DELETE语句需要的行锁更少。

当然基于行的复制同样也有缺点,就是需要更大的存储空间去存储每条记录详细修改情况。例如DELETE FROM a;如果a表由100W条记录,这100W条记录都会写入binlog里面去。由于此时可能导致binlog文件被锁定更长的时间,所以可能会造成并发问题。采用 binlog_row_image=minimal 大大减少了缺点。

对于使用MyISAM 存储引擎的INSERT表,将其作为基于行的事件应用于二进制日志时,与将其用作语句时相比,需要在从属服务器上对语句进行更强的锁定 。这意味着MyISAM在使用基于行的复制时,不支持在表上进行并发插入。