主从复制一之概述

  • Post author:
  • Post category:其他


大部分应用对数据库而言都是“ 读多写少 ”,也就说对数据库读取数据的压力比较大,

有一个思路就是采用数据库集群的方案,做 主从架构 、进行 读写分离 ,这样同样可以提升数据库的并发处理能力。但并不是所有的应用都需要对数据库进行主从架构的设置,毕竟设置架构本身是有成本的。

如果目的在于提升数据库高并发访问的效率,那么首先考虑的是如何 优化SQL和索引 ,这种方式

简单有效;其次才是采用 缓存的策略 ,比如使用 Redis将热点数据保存在内存数据库中,提升读取的效率;最后才是对数据库采用 主从架构 ,进行读写分离。

一、主从复制的作用

1、读写分离

master是主库,负责写数据,为写库。

slave为从库,负责读取数据,称为读库。

当主库进行更新时候,会自动将数据复制到从库中,我们在客户端读取数据的时候,会从从库进行读取。

面对“读多写少”的需求,采用读写分离的方式,可以实现更高的并发访问,同时还能对从服务器进行负载均衡,让不同的读请求按照策略均匀分发到不同的从服务器上,让读取增加流畅。读取流畅的另一个原因是减少了锁表的影响,比如让主库负责写,当主库出现写锁时,不会影响从库的select读取。

2、数据备份

3、高可用性

数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性。高可用性可以通过一个指标来衡量,即正常使用时间/全年时间。比如要达到全年99.999%的时间都可用,就意味着系统在一年中不可用的时间不得超过365*24*60(1-99.999%)=5.256分钟(含系统崩溃时间,日常维护导致的停机时间)

二、主从复制的原理

Slave 会从 Master 读取 binlog 来进行数据同步

实际上主从同步的原理就是基于 binlog 进行数据同步的。在主从复制过程中,会基于3个线程来操作,一个主库线程,两个从库线程。

1、二进制日志转储线程(Binlog dump thread)

是一个主库线程。当从库线程连接的时候, 主库可以将二进制日志发送给从库,当主库读取事件(Event)的时候,会在 Binlog 上加锁 ,读取完成之后,再将锁释放掉。

2、从库 I/O 线程

会连接到主库,向主库发送请求更新 Binlog。这时从库的 I/O 线程就可以读取到主库的二进制日志转储线程发送的 Binlog 更新部分,并且拷贝到本地的中继日志 (Relay log)

3、从库 SQL 线程

读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步

三、主从配置

主从所有配置项都配置在 [mysqld] 节点下,且都是小写字母

1、主机配置文件


(1)必选

#[必须]主服务器唯一ID


server-id=1


#[必须]启用二进制日志,指名路径。比如:自己本地的路径/log/mysqlbin


log-bin=log-bin


(2)可选

#[可选] 0(默认)表示读写(主机),1表示只读(从机)


read-only=0


#设置日志文件保留的时长,单位是秒


binlog_expire_logs_seconds=6000


#控制单个二进制日志大小。此参数的最大和默认值是1GB


max_binlog_size=200M


#[可选]设置不要复制的数据库


binlog-ignore-db=test


#[可选]设置需要复制的数据库,默认全部记录。比如:binlog-do-db=master_slave


binlog-do-db=需要复制的主数据库名字


#[可选]设置binlog格式


binlog_format=STATEMENT

2、从机配置文件

(1)必选

#[必须]从服务器唯一ID


server-id=2

(2)可选

#[可选]启用中继日志


relay-log=mysql-relay

四、binlog格式设置

1、STATEMENT模式

基于SQL语句的复制(statement-based replication, SBR)

binlog_format=STATEMENT

每一条会修改数据的sql语句会记录到binlog中。这是默认的binlog格式。

(1)优点

1)历史悠久,技术成熟

2)不需要记录每一行的变化,减少了binlog日志量,文件较小

3)binlog中包含了所有数据库更改信息,可以据此来审核数据库的安全等情况

4)binlog可以用于实时的还原,而不仅仅用于复制

5)主从版本可以不一样,从服务器版本可以比主服务器版本高

(2)缺点

1)不是所有的UPDATE语句都能被复制,尤其是包含不确定操作的时候。

LOAD_FILE()、UUID()、USER()、FOUND_ROWS()、SYSDATE()(除非启动时启用了 –sysdate-is-now 选项)

2)INSERT … SELECT 会产生比 RBR 更多的行级锁

3)复制需要进行全表扫描(WHERE 语句中没有使用到索引)的 UPDATE 时,需要比RBR请求更多的行级锁

4)对于有 AUTO_INCREMENT 字段的 InnoDB表而言,INSERT 语句会阻塞其他 INSERT 语句

5)对于一些复杂的语句,在从服务器上的耗资源情况会更严重,而 RBR 模式下,只会对那个发生变化的记录产生影响

6)执行复杂语句如果出错的话,会消耗更多资源

7)数据表必须几乎和主服务器保持一致才行,否则可能会导致复制出错

2、ROW模式

基于行的复制(row-based replication, RBR)

binlog_format=ROW

5.1.5版本的MySQL才开始支持,不记录每条sql语句的上下文信息,仅记录哪条数据被修改了,修改成什么样了

(1)优点

1)任何情况都可以被复制,这对复制来说是最 安全可靠 的。(比如:不会出现某些特定情况下的存储过程、function、trigger的调用和触发无法被正确复制的问题)

2)多数情况下,从服务器上的表如果有主键的话,复制就会快了很多

3)复制以下几种语句时的行锁更少:INSERT … SELECT、包含 AUTO_INCREMENT 字段的 INSERT、没有附带条件或者并没有修改很多记录的 UPDATE 或 DELETE 语句

4)执行 INSERT,UPDATE,DELETE 语句时锁更少

5)从服务器上采用 多线程 来执行复制成为可能

(2)缺点

1)binlog 大了很多

2)复杂的回滚时 binlog 中会包含大量的数据

3)主服务器上执行 UPDATE 语句时,所有发生变化的记录都会写到 binlog 中,而 SBR 只会写一次,这会导致频繁发生 binlog 的并发写问题

4)无法从 binlog 中看到都复制了些什么语句

3、MIXED模式

混合模式复制(mixed-based replication, MBR)

binlog_format=MIXED

从5.1.8版本开始,MySQL提供了Mixed格式,实际上就是Statement与Row的结合

在Mixed模式下,一般的语句修改使用statment格式保存binlog。如一些函数,statement无法完成主从复制的操作,则采用row格式保存binlog

MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。