HA
MHA
(1)从宕机崩溃的master保存二进制日志事件(binlog events);
(2)识别含有最新更新的slave;
(3)应用差异的中继日志(relay log)到其他的slave;
(4)应用从master保存的二进制日志事件(binlog events);
(5)提升一个slave为新的master;
(6)使其他的slave连接新的master进行复制;
MGR
MySQL 组复制实现了基于复制协议的多主更新(提一下和Oracle RAC的不同)
1)复制组由多个 server成员构成,并且组中的每个 server 成员可以独立地执行事务。但所有读写(RW)事务只有在冲突检测成功后才会提交。只读(RO)事务不需要在冲突检测,可以立即提交。
2)换句话说,对于任何 RW 事务,提交操作并不是由始发 server 单向决定的,而是由组来决定是否提交。准确地说,在始发 server 上,当事务准备好提交时,该 server 会广播写入值(已改变的行)和对应的写入集(已更新的行的唯一标识符)。然后会为该事务建立一个全局的顺序。最终,这意味着所有 server 成员以相同的顺序接收同一组事务。因此,所有 server 成员以相同的顺序应用相同的更改,以确保组内一致。
3)组复制使您能够根据在一组 server 中复制系统的状态来创建具有冗余的容错系统。因此,只要它不是全部或多数 server 发生故障,即使有一些 server 故障,系统仍然可用,最多只是性能和可伸缩性降低,但它仍然可用。server 故障是孤立并且独立的。它们由组成员服务来监控,组成员服务依赖于分布式故障检测系统,其能够在任何 server 自愿地或由于意外停止而离开组时发出信号。
4)他们是由一个分布式恢复程序来确保当有 server 加入组时,它们会自动更新组信息到最新。并且多主更新确保了即使在单个服务器故障的情况下也不会阻止更新,不必进行 server故障转移。因此,MySQL 组复制保证数据库服务持续可用。
5)值得注意的一点是,尽管数据库服务可用,但当有一个 server 崩溃时,连接到它的客户端必须定向或故障转移到不同的 server。
MySQL 组复制提供了高可用性,高弹性,可靠的 MySQL 服务。
MGR的局限
仅支持InnoDB表,并且每张表一定要有一个主键,用于做write set的冲突检测;
必须打开GTID特性,二进制日志格式必须设置为ROW,用于选主与write set
COMMIT可能会导致失败,类似于快照事务隔离级别的失败场景
目前一个MGR集群最多支持9个节点
不支持外键于save point特性,无法做全局间的约束检测与部分部分回滚
二进制日志不支持binlog event checksum
Replication
半同步复制
AFTER_SYNC 这个即新的半同步方案,Waiting Slave dump在Storage Commit之前。
AFTER_COMMIT 老的半同步方案。
MySQL组提交(group commit)
binlog_group_commit_sync_delay
slave_parallel_workers
组提交与并行复制,减少主从延迟
GTID原理、使用GTID跳过复制错误
主从延时或同步终止的原因
- 大事务,binlog写入是事务级的,有大事务存在的话会导致瞬时写入的binlog较大,从库的io thread压力到导致延迟
- 网络延时
- 主从两台机器的负载不一致
- 自增长键冲突导致主从不一致
- mysql异常宕机情况下,如果未设置sync_binlog=1或者innodb_flush_log_at_trx_commit=1很有可能出现binlog或者relaylog文件出现损坏,导致主从不一致
- max_allowed_packet设置不一致导致延时
解决办法
- 大事务改造,binlog写入是事务级的,有大事务存在的话会导致瞬时写入的binlog较大,从库的io thread压力到导致延迟
- 使用relay-fetch进行预热,提高从库应用日志的速度
- 调整双1,业务安全允许的情况下(半同步复制时可以考虑)
- 开启多线程复制,show variables like '%slave_parallel%'(配合组提交,5.7)
- 调整从库的max_allowed_packet不应小于主库
MySQL会根据配置文件会限制server接受的数据包的大小。如果写入大数据时,因为默认的配置太小,插入和更新操作会因为 max_allowed_packet 参数限制,而导致失败。备份
xtrabackup
1.innobackupex 在启动后,会先 fork 一个进程,启动 xtrabackup进程,然后就等待 xtrabackup 备份完 ibd 数据文件;
2.xtrabackup 在备份 InnoDB 相关数据时,是有2种线程的,1种是 redo 拷贝线程,负责拷贝 redo 文件,1种是 ibd 拷贝线程,负责拷贝 ibd 文件;redo 拷贝线程只有一个,在 ibd 拷贝线程之前启动,在 ibd 线程结束后结束。xtrabackup 进程开始执行后,先启动 redo 拷贝线程,从最新的 checkpoint 点开始顺序拷贝 redo 日志;然后再启动 ibd 数据拷贝线程,在 xtrabackup 拷贝 ibd 过程中,innobackupex 进程一直处于等待状态(等待文件被创建)。
3.xtrabackup 拷贝完成idb后,通知 innobackupex(通过创建文件),同时自己进入等待(redo 线程仍然继续拷贝);
4.innobackupex 收到 xtrabackup 通知后,执行FLUSH TABLES WITH READ LOCK (FTWRL),取得一致性位点,然后开始备份非 InnoDB 文件(包括 frm、MYD、MYI、CSV、opt、par等)。拷贝非 InnoDB 文件过程中,因为数据库处于全局只读状态,如果在业务的主库备份的话,要特别小心,非 InnoDB 表(主要是MyISAM)比较多的话整库只读时间就会比较长,这个影响一定要评估到。
5.当 innobackupex 拷贝完所有非 InnoDB 表文件后,通知 xtrabackup(通过删文件) ,同时自己进入等待(等待另一个文件被创建);
6.xtrabackup 收到 innobackupex 备份完非 InnoDB 通知后,就停止 redo 拷贝线程,然后通知 innobackupex redo log 拷贝完成(通过创建文件);
7.innobackupex 收到 redo 备份完成通知后,就开始解锁,执行 UNLOCK TABLES;
8.最后 innobackupex 和 xtrabackup 进程各自完成收尾工作,如资源的释放、写备份元数据信息等,innobackupex 等待 xtrabackup 子进程结束后退出。
SQL优化
semi-join 针对insubquery,不会返回重复的记录,遇到满足条件的第一条记录则返回并开始下一个条件的查询
index condition push down
block nest loop
multi-range read 根据查询语句中的二级索引查找到索引值后,再根据二级索引中的主键排序,取数时可极大的节省IO(相当于合并IO)
extra中出现using temporary表示查询使用临时表,需关注
extra中出现file sort 不一定使用了文本排序,也可能是在内存中排序,只是说排序操作未利用索引,需关注
利用索引组织表的特性进行SQL优化
在线DDL
5.7何时会降级为copy的方式?
B树和B+树的区别
锁
MySQL中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的?
Innodb的行锁是加在索引实现的;
原因是:innodb是将primary key index和相关的行数据共同放在B+树的叶节点;innodb一定会有一个primary key,secondary index查找的时候,也是通过找到对应的primary,再找对应的数据行;
监控
profiling分析SQL执行过程
show processlist结合awk工具实施监控
更新performance_schema 中的setup开头的表,可以记录更多数据库运行信息至event表
(1)QPS(每秒Query量)
QPS = Questions(or Queries) / seconds
mysql > show global status like 'Question%';
(2)TPS(每秒事务量)
TPS = (Com_commit + Com_rollback) / seconds
mysql > show global status like 'Com_commit';
mysql > show global status like 'Com_rollback';
(3)key Buffer 命中率
mysql>show global status like 'key%';
key_buffer_read_hits = (1-key_reads / key_read_requests) 100%
key_buffer_write_hits = (1-key_writes / key_write_requests) 100%
(4)InnoDB Buffer命中率
mysql> show status like 'innodb_buffer_pool_read%';
innodb_buffer_read_hits = (1 - innodb_buffer_pool_reads / innodb_buffer_pool_read_requests) * 100%
(5)Query Cache命中率
mysql> show status like 'Qcache%';
Query_cache_hits = (Qcahce_hits / (Qcache_hits + Qcache_inserts )) * 100%;
(6)Table Cache状态量
mysql> show global status like 'open%';
比较 open_tables 与 opend_tables 值
(7)Thread Cache 命中率
mysql> show global status like 'Thread%';
mysql> show global status like 'Connections';
Thread_cache_hits = (1 - Threads_created / connections ) * 100%
#####################################################
interactive_timeout
我们可以适当设置这个值,8小时太长了,不适用于生产环境。因为一个连接长时间不工作,还占用我们的连接数,会消耗我们的系统资源。
体系原理
两阶段提交,保证redo和binlog顺序一致,xtrabackup有这个要求
double write
insert buffe/change buffer
刷新临近页
异步IO
MVCC原理阐述
行中有隐含字段 DB_TRX_ID、DB_ROLL_PTR,利用回滚段实现多版本
基本特征
每行数据都存在一个版本,每次数据更新时都更新该版本。
修改时Copy出当前版本随意修改,各个事务之间无干扰。
保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)
InnoDB存储引擎MVCC的实现策略
在每一行数据中额外保存两个隐藏的列:当前行创建时的版本号和删除时的版本号(可能为空,其实还有一列称为回滚指针,用于事务回滚,不在本文范畴)。这里的版本号并不是实际的时间值,而是系统版本号。每开始新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询每行记录的版本号进行比较。
每个事务又有自己的版本号,这样事务内执行CRUD操作时,就通过版本号的比较来达到数据版本控制的目的。
分库分表
简单介绍下MyCat,DRDS,TDDL
分库分表的原则是,尽量不分库分表
讲述TiDB项目经验
全局ID
分布式事务XA
分库分表思路
linux调优
1.使用符号链接分散IO,建表时指定data directory
2.禁止操作系统更新文件的atime属性
3.用裸设备存放innodb共享表空间(buffer pool中缓存了数据和索引,不需要文件系统缓存)
4.调整IO调度算法,mysql建议使用deadline调度算法
参数调优
innodb_flush_method=O_DIRECT
O_DIRECT相比fdatasync的优点是避免了双缓冲,本身innodb buffer pool就是一个缓冲区,不需要再写入到系统的buffer,但是有个缺点是由于是直接写入到磁盘,所以相比fdatasync的顺序读写的效率要低些。在大量随机写的环境中O_DIRECT要比fdatasync效率更高些,顺序写多的话,还是默认的fdatasync更高效。