大部分应用对数据库而言都是“ 读多写少 ”,也就说对数据库读取数据的压力比较大,
有一个思路就是采用数据库集群的方案,做 主从架构 、进行 读写分离 ,这样同样可以提升数据库的并发处理能力。但并不是所有的应用都需要对数据库进行主从架构的设置,毕竟设置架构本身是有成本的。
如果目的在于提升数据库高并发访问的效率,那么首先考虑的是如何 优化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之间选择一种。