3.1 MySQL复制
为了保证应用24小时提供服务,那么咱们须要作2件事情,系统数据的备份和冗余。备份能够将数据恢复到崩溃以前的状态,而冗余则是保证在一个或多个节点中止服务的状况下,应用仍能提供服务。mysql
3.1.1 什么是复制
这里说的复制,就是指MySQL复制主节点(master)的全部数据改变到从节点(slave),并应用改变的数据,与主节点数据保存一致。一般复制就是为了给master建立一个可靠的副本。sql
MySQL复制,有什么特色呢?数据库
(1) 数据分布 (Data distribution ),数据能够分布在不一样的数据中心。安全
(2) 负载平衡(load balancing),能够分配查询,下降主服务器压力。服务器
(3) 备份(Backups) ,复制自己就是一种master的备份。网络
(4) 高可用性和容错行 High availability and failover,当master宕机后,slave能够接管master的任务,同时具备及时纠正错误,挽回数据的容错率。并发
从MySQL5.0开始,MySQL默认采用日志复制,效率很是高,可靠性也很是高,前提是主从,一开始是彻底相同的数据。当没法保证精准复制时,MySQL会基于行的复制。异步
3.1.2 异步与同步的区别
MySQL的复制准确的说,是异步的,不是同步复制的。事务首先在主节点提交,而后复制给从节点,并在从节点上应用。这意味着主节点和从节点可能并不一致,若是主节点一直在更新,那么从节点始终是落后与主节点的。函数
异步复制优势在于,比同步复制更快,扩展性更好,占用系统资源更少。高并发
同步复制则须要master等待全部的slave的写都完成后,才能提交,致使写的速度大大下降,同时须要额外的同步机制来保证一致性,但却有额外的通讯消息传递,增长了网络数据量。
3.2 主从复制
搭建一个主从复制,大体看看是一个什么样的效果,一主一从,最简单的开始。
这里须要涉及到二进制日志,后面来详细说明,本次主要说明复制过程。
3.2.1 配置复制
第一步:配置master。首先须要开启二进制日志,配置好server-id,而后启动MySQL,以下所示几行添加到/etc/my.cnf文件中:
log-bin=master-bin 二进制日志文件名称格式。
log-bin-index=master-bin.index 二进制日志的索引文件名
server-id=1 server id用于标示主从。
通常状况下log-bin默认是hostname-bin。Hostname的值来自pid-file选项,可是这样也会有问题,主机名修改以后,binlog日志文件名也会随之改变,索引文件仍是能够读取到正确的值。
当不给log-bin-index值的时候,默认与binlog文件基本名相同,索引文件随主机名改变而改变,当你重启了服务器以后,索引文件就找不到日志文件了,认为不存在了。
接下来,须要建立一个复制用的用户。例如:

mysql> change master to
-> master_host='vm11.qq.com',
-> master_port=3306,
-> master_user='repl_user',
-> master_password='mysql';
Query OK, 0 rows affected, 2 warnings (0.04 sec)

注意:最好在同步以前,主从两边的数据库是同样的,由于master在没有开启二进制日志以前的全部操做都不会同步过去到slave的。
咱们这里在master没有开启二进制日志以前,先创建了一个库test,slave确定同步不过去,这时候master删除这个库。而后再次新建test的时候,出现了问题。

这是master的,看看slave的。

这里没有同步过去,看看什么问题。

错误:1008,test库不存在,drop database test语句执行不了,因此slave_sql_running状态变成了NO。生产环境很容易忽略,出现这样的问题。

CHANGE MASTER TO MASTER_HOST='vm11.qq.com',
MASTER_USER='repl_user',
MASTER_PASSWORD='mysql',
MASTER_LOG_FILE='master-bin.000001',
MASTER_LOG_POS=756;
Start slave;重新的位置重新同步,前面的忽略。
3.2.2 二进制日志
什么是二进制日志,就是记录表改变的记录,以上例来看。

来看看日志都记录了什么;

对比一下,咱们如下的操做,那些记录了,那些没有记录。
mysql> create database test; 记录
mysql>use test; 记录
mysql>create table tab(text text); 记录
mysql>insert into tab values("hello!"); 记录,自动添加use test命令。
mysql>select * from tab; 没有,日志记录了一次commit;
mysql> flush logs; 记录
最后一条记录:Info:master-bin.000002;pos=4是slave下一次读取二进制日志的位置,由于咱们执行了flush logs;强制切换日志。
当咱们想看第二个日志文件的内容时,默认是没法看到的,能够这样:
mysql> show binlog eventsin 'master-bin.000002' \G;
3.2.3 复制工做原理
总体上来讲,复制有3个步骤:
(1) master将改变记录到二进制日志(binary log)中(这些记录叫作二进制日志事件,binary logevents);
(2) slave将master的binary log events拷贝到它的中继日志(relay log);
(3) slave重作中继日志中的事件,将改变反映它本身的数据。

1.基于语句复制
也称为逻辑复制,须要保证主从基础数据同样,而后把主库上记录的更改在从库上再执行一遍,实现简单,同步效果较好,网络传输少,但问题就是,存在着一些没法被正确复制的SQL,像时间戳,current_user()这样的函数语句,触发器,存储过程等也容易出现问题。另一个问题时更新必须串行的,因此会须要更多的锁。
优势:适应场景普遍,能够很是灵活,都是SQL执行方式,当出现问题能够很好的去定位。
缺点:有些语句存在没法正确复制问题,特别是存储过程和触发器。
2.基于行的复制
就是直接复制改变的行数据,在从库中也作update操做,也种实现方式比较复杂,由于复制的数据可能不正确,从库更新量大,主库一个update操做更新2000条数据,但在从库可能须要update2000次才能将数据与主库保持一致,优势是直接复制数据,会比较高效,不用去分析日志,可是缺点也很是明显。网络传输量较大,
优势:这种方式什么状况均可以使用,存储过程,触发器等都没有问题,可是备库与主库的字段有不一致的状况,那么复制就会失败。
缺点:没法获知执行了什么操做,只能看到变化了的值,当问题出现后,很难去判断故障的缘由,或是什么致使的,并且不少状况下,备库的开销很是大,并且网络传输也更高。
3.2.4 推荐复制配置
此小结主要用来分析复制的配置,有些配置是没有必要的,有些也是须要分适用场景的,主要仍是以安全为第一,最小化可能出现的问题为前提,而后是性能上的建议。
主库上最重要的一个参数:sync_binlog=1
开启,MySQL每次提交事务前都会将二进制日志同步到磁盘上,可以保证崩溃时不丢失事务,关闭则无需再提交以前写到磁盘,对于中继日志来讲,不适用该参数,因此建议主库上开启,从库上关闭。
若是使用InnoDB,那么建议配置如下设置:
innodb_flush_logs_at_trx_commit:设为1固然是最安全的,但性能页是最差的(相对其余两个参数而言,但不是不能接受)。若是对数据一致性和完整性要求不高,彻底能够设为2,若是只最求性能,例如高并发写的日志服务器,设为0来得到更高性能。
Innodb_support_xa=1 保证binlog里面存在的事务必定在redo log里面存在,同时binlog里面事务顺序与redo log事务顺序一致。
Innodb_safe_binlog 表示在5.0版本以前,跟Innodb_support_xa参数意思同样。
log-bin=/data/binlog/master-bin 必定要配置文件名,否则在其它应用的时候,容易出现问题,同时制定了它的路径。
在备库上推荐配置:
Relay_log=/data/relaylog/relay-bin 制定路径避免不一样版本之间的bug问题,
Skip_slave_start 表示备库在崩溃后不自动复制,由于可能已经不一致了,自动复制,可能致使更多的损坏,因此通常都须要禁用掉。
Read_only 能够阻止大部分用户更改非临时表,除了SQL线程和超级权限用户外。
3.2.5 复制延迟
复制延迟,在大部分的同步系统中,都存在这样的问题,目前较为成熟的亚秒级实时同步的解决方案是GoldenGate,固然大部分系统是不须要这么高的要求,因此只要延迟在咱们接受的范围内都是科学的解决方案。
复制延迟通常存在2种:一种是产生延迟而后再跟上,一种是稳定的延迟增大,前一种基本都是因为运行一条运行很长时间的查询致使,然后者,可能存在很是严重的问题致使。一般没有太大的调优空间,简单的办法是配置InnoDB,能够不那么频繁的刷新磁盘,事务提交更快。能够设置innodb_flush_log_at_trx_commit值为2来作,还能够禁止备库上的二进制日志记录,配置innodb_locks_unsafe_for_binlog为1,并配置MyISAM的delay_key_write为all,但这些都是牺牲安全为代价提高效率,还有一点,是这样配置备库后,那么这个永远就只能是备库,不能切换为主库了,若是须要切换,须要将配置改回来。
优化主库高代价操做
在主库上任何昂贵的操做,都会在备库上重复一次,某些工做能够移动到备库,就不会让高代价的操做在主从上执行2次。例如:一个大表,须要汇总到一个小表用于平常维护:
Replayce into s_db.ip_table(col1,col2,…)
Select col1,sum(col2,….) from s_db.epc_table group by col1;
若是在主库上执行,那么备库也须要执行庞大的group by操做,当进行的太多的话,那么备库就容易跟不上了,若是在备库上操做,完成以后能够select into outfile,而后再load data infile将结果集加载到主库中,这样重负的工做变成了load data infile操做了。
备库并行写入
因为备库要求串行写入,某些应用更新就很吃力,那么咱们能不能并行写入呢,固然复制自己是不具有的,这须要区分写入的类别了,例如禁止归档日志记录到二进制日志,而后再主库和备库上分别执行,提升效率,这就是OLTP系统的归档数据操做,每每这样来作比让数据库本身靠复制完成要高效的多。
还须要注意一个问题,主库和备库的max_allowed_packet配置不一致,主库可能会记录一个备库认为过大的包,备库获取到该二进制事件后,可能会无限报错和重试,或中继日志损坏。
3.2.6 半同步和复制心跳
半同步复制在提交过程当中增长了一个延迟,当提交事务时,客户端接收到查询结束反馈前必须保证二进制日志已经传输到至少一台备库上。主库将事务提交到磁盘上以后会增长一个延迟。那么速度上延迟增长,但同步复制也会增长2段提交,增长的额外消息交换而性能不高。
也就是说主库执行完事务后,是不会管备库进度的,这样提升了主库的效率,而备库上的事务至少有一个是跟主库一致的,因此某种程度上讲,实现了事务同步,不保证备库已经执行完成,在性能上主库提高较大。
复制心跳,就是主库和备库相互联系功能,避免不声不响的断开链接。当出现断开链接,备库会注意到丢失的心跳数据,当再次恢复的时候,以此为依据,再次同步数据。