MySQL 集群架构、性能问题排查和优化方法 | 进阶技巧

如今越来越多的企业都将核心业务运行在MySQL之上,与此同时,大数据量大流量带来的性能问题也愈演愈烈,数据库的操作往往成为整个系统的瓶颈,如何使MySQL跑得更快已是一项迫在眉睫的任务。

数据库性能优化是一个复合性问题,涉及存储、OS、数据库配置参数、SQL优化、系统架构等多个领域,因此优化工作常常需要开发与运维协作进行。

存储和OS优化基本已有成熟的最佳实践,比如使用SSD磁盘(线上业务必选)、搭建Raid10、特定的内核参数等。数据库配置参数可以解决部分问题,但是效果有限且有时需要停机维护。常用的性能优化主要基于SQL、索引、表结构、应用架构。

针对这些问题,社区组织了线上答疑活动对大家的疑问进行了解答,本篇文章将这些问题按以下板块进行了梳理,供大家参考:1. MySQL集群架构;2. 性能问题排查;3. 优化方法;4. 其他问题

【答疑嘉宾】刘诚杰,平安城科高级DBA,多年MySQL与MongoDB运维经验,负责公司所有数据库的日常运维、优化、选型与架构设计。

本文由刘诚杰梳理,在此感谢 ACDante、zymh_zy、counship 、大力水手 等人的解答。


1. MySQL集群架构


Q:MySQL有哪些开源的主流集群架构?

问题描述:MySQL原厂有Oracle的cluster集群,有哪些主流的开源适合高并发集群呢?

答:

一、MySQL高可用方案

MySQL以及各种开源数据库,也有自身的集群方案,但是大多需要和业务以及借助第三方工具来实现。或者通过分布式来均衡高并发。主要的高可用集群架构可以分为如下几种:

1、基于共享存储的高可用方案--SAN

基于共享存储的高可用,及使用传统的基于SAN共享存储,结合开源的Keeplive做主从同步,可避免除存储外的组件损坏引起的宕机,部署相对简单,对应用透明,但是存储时单点,且存在性能瓶颈

2、基于磁盘复制的高可用方案-DRBD

保证主备的数据一致性,不依赖共享存储,此方案处理failover的方式上依旧需要借助主机层面的高可用组件,如keeplive,Heartbeat等。不同的是,在数据共享方面,采用了基于块级别的数据同步软件DRBD来实现,,但是可扩展性较差。它并不共享存储,而是通过服务器之间的网络复制数据。

适用于数据库访问量不太大,短期内访问量增长不会太快,对数据库可用性要求非常高的场景。

3、基于MySQL自身的主从复制-Replication

基于MySQL自身的主从复制,5.7以后的GTID,以及之前的replication。主从复制,部署简单,但是只能有一个Master进行读写,其余都为备库,还需要结合业务。并发量不大的情况下,可采取主从,管理简单。

4、MHA高可用方案

MHA是一套MySQL高可用管理软件,除了检测Master宕机后,提升候选Slave为New Master之外(漂虚拟IP),还会自动让其他Slave与New Master 建立复制关系。 MHA Manager可以单独部署在一台独立的机器上,并管理多个master-slave集群。但是,只支持一主多从架构,集群中必须最少有三台数据库服务器,要保持切换对应用透明,依然依赖于VIP,不适用于大规模集群部署,配置比较复杂。且MHA管理节点本身的HA无法保证。

MySQL 5.7 之前数据不丢的前提是Master服务器还可以被MHA Manager进行SSH连接,通过应用保存的binlog 的方式来保证。

MySQL 5.7 之后通过无损复制, 仅仅是减少了丢数据的可能性,假如此时的状态为切成异步的状态,那就和之前一样了(可以设置超时的时间很大);当Master恢复的时候,最后一部分数据是否需要Flashback,MHA也是不负责这个事情,需要人工介入。

5、基于zookeeper/consul的高可用方案

借助zookeeper组件,结合MHA或者其他高可用架构场景,实现强制一致性的高可用集群分布,可适应大规模高并发场景,需要一定的技术实力,引入zookeeper,架构复杂度上升,但是整体扩展性非常好,可以管理大规模集群。保证了整个系统的高可用,主从的强一致依赖于MySQL本身,比如半同步,或者外围工具的回补策略

6、基于MMM高可用方案

MMM提供了MySQL主主复制配置的监控、故障转移和管理的一套可伸缩的脚本套件。在MMM高可用方案中,典型的应用是双主多从架构,通过MySQL replication技术可以实现两个服务器互为主从,且在任何时候只有一个节点可以被写入,避免了多点写入的数据冲突。同时,当可写的主节点故障时,MMM套件可以立刻监控到,然后将服务自动切换到另一个主节点,继续提供服务,从而实现MySQL的高可用。可以灵活选择VIP方案或者全局目录数据库方案(更改Master IP映射)来进行切换。

MMM提供了自动和手动两种方式移除一组服务器中复制延迟较高的服务器的虚拟ip,同时它还可以备份数据,实现两节点之间的数据同步等。由于MMM无法完全的保证数据一致性,所以MMM适用于对数据的一致性要求不是很高,但是又想最大程度的保证业务可用性的场景。对于那些对数据的一致性要求很高的业务,非常不建议采用MMM这种高可用架构。

7、基于中间件proxy高可用组件的集群方案

中间件:

阿里 Cobar、MyCAT

360 Atlas

淘宝 Tddl

网易 Cutus

MySQLProxy

ProxySQL(Percona)

KingShard

MaxScale(MariaDB)

OneProxy

切换对应用透明,可扩展性强,方便分片扩展,可以跨机房部署切换,但是需要有一定自研能力,或者选择有完整的后期技术支持的中间件,以及社区活跃度较高的,有一定能力,后期可自研或者自己优化开发相关的中间件。以适应自身的业务需求。

二、集群/分布式

基于集群或者分布式的HA包括:

Mysql Group Replication

Mysql InnoDB Cluster

Percona XtraDB Cluster

MariaDB Galera Cluster

1、MGR

关于MGR原理,可参考可以参考阿里的数据库内核月报,关于mgr的文档。 http://mysql.taobao.org/monthly/2017/08/01/

基于传统异步复制和半同步复制的缺陷——数据的一致性问题无法保证,MySQL官方在5.7.17版本正式推出组复制(MySQL Group Replication,简称MGR)。 由若干个节点共同组成一个复制组,一个事务的提交,必须经过组内大多数节点(N / 2 + 1)决议并通过,才能得以提交。如上图所示,由3个节点组成一个复制组,Consensus层为一致性协议层,在事务提交过程中,发生组间通讯,由2个节点决议(certify)通过这个事务,事务才能够最终得以提交并响应。

引入组复制,主要是为了解决传统异步复制和半同步复制可能产生数据不一致的问题。组复制依靠分布式一致性协议(Paxos协议的变体),实现了分布式下数据的最终一致性,提供了真正的数据高可用方案。

2、MySQL InnoDB Cluster

Cluster解决方案其实是由MySQL的几个不同产品和技术组成的,比如MySQL Shell, MySQL Router, Group Replication. 一组MySQL服务器可以配置为一个MySQL集群。在默认的单主节点模式下,集群服务器具有一个读写主节点和多个只读辅节点。辅助服务器是主服务器的副本。客户端应用程序通过MySQL Router连接到主服务程序。如果主服务连接失败,则次要的节点自动提升为主节点,MySQL Router请求到新的主节点。InnoDB Cluster不提供NDB Cluster支持

3、Percona XtraDB Cluster

官网地址:https://www.percona.com/doc/percona-xtradb-cluster/5.7/intro.html

节点在接收sql 请求后,对于ddl 操作,在commit之前,由WSREP API 调用galera 库进行集群内广播,所有其他节点验证成功后事务在集群所有节点进行提交,反之rollback。pxc 保证整个集群所有数据的强一致性,满足CAP理论中满足:Consistency 和 Availability。

PXC提供的特性

同步复制,事务要么在所有节点提交或不提交

多主复制,可以在任意节点进行写操作

在从服务器上并行应用事件,真正意义上的并行复制

节点自动配置

数据一致性,不再是异步复制

限制:

只支持INNODB表

不允许大事务的产生(否则的话后果很严重)

写性能取决于最差的节点

不能解决热点更新问题

乐观锁控制

对于写密集型应用需要控制单个节点的大小,单个节点数据越大,新加节点如果采用自动添加可能产生很大抖动(添加节点建议用备份或者备份+binlog 进行IST(Incremental State Transfer)增量同步


Q:目前银行主流的MySQL高可用采用哪种方式,MHA还是MGR?

问题描述:目前银行主流的MySQL高可用采用哪种方式?MHA还是MGR,各自的优缺点是什么?各自有哪些坑需要注意?

答:银行主流何种MySQL高可用方案不太了解。可能是主从+中间件+自研套件的模式。

由于MGR技术相对较新,目前使用MHA更多。但个人认为,MGR或者基于此的innodb cluster架构(或替代方案)会成为未来主流。

MHA:

优点:成熟稳定,自动切换主从,主节点宕机后尽可能少丢失数据(自动抓取未复制的binlog)。

缺点:管理节点单点、可能脑裂、可能有不必要切换、还是有丢数据风险、组件多维护相对麻烦

MGR:

优点:基于paxos的高可用架构,支持多主(不建议),强一致

缺点:需要innodb引擎(丢业务有改造代价),应用端没有自动切换(可以通过中间件解决),技术太新可能有未知bug

其他的话还有PXC,但是因为性能问题不太建议。


Q:DB2 可以做HADR,Oracle可做ADG,OGG,MySQL可做什么集群?

问题描述:不懂MySQL,想问下MySQL怎么做集群,HA,数据复制方式怎么做?

答1:mysql最简单就是主从(类似逻辑adg)

物理dg的话需要借助第三方工具

没有传统意义的ogg\rac等

答2:方案很多:主从复制;Galera协议;NDB引擎;中间件/proxy;共享存储;主机高可用;


2. 性能问题排查


Q:MySQL如何排查cpu占用高的问题?

问题描述:重点是关于通过哪些系统表或者常用的sql来确定导致问题的sql?感觉这方面的资料很少,不像oralce的哪些v$视图,网上资料很多,sql语句也很多。

答:可以通过将系统线程号与SQL对应来查看

top -H -p <mysqld进程id>

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

23974 mysql 20 0 1658m 358m 12m R 99.9 1.1 0:05.52 mysqld

12295 mysql 20 0 1658m 358m 12m S 0.3 1.1 0:02.44 mysqld

....


SELECT a.THREAD_OS_ID,b.user,b.host,b.db,b.command,b.time,b.state,b.info

FROM performance_schema.threads a,information_schema.processlist b

WHERE b.id = a.processlist_id;


THREAD_OS_ID USER HOST db command TIME state info

** 23974 ** root 10.10.18.201:21466 sys QUERY 29 Sending DATA SELECT a.* FROM test a,test b,test c ,test d ORDER BY a.value LIMIT 0, 1000

....


Q:MySQL数据库内存使用率高,应该如何进行排查?

问题描述:内存使用率,通过系统命令能定位到mysql占用的内存高,如何通过系统表或者相关的sql语句,定位到占用内存高的那部分sql?

答:淘宝内核月报的这边文章值得一看,推荐一下:

http://mysql.taobao.org/monthly/2018/11/08/

排查思路,排查方法都涉及。

Mysql Server Memory Usage= Sum of Global Buffers + (number of Connection * Per thread memory variables)

a)单个mysql连接线程的内存消耗统计,这里只是统计分配值(具体驻留内存占用值统计不到)

select b.thd_id, b.user, current_count_used,current_allocated, current_avg_alloc, current_max_alloc,total_allocated,current_statement from memory_by_thread_by_current_bytes a,session b where a.thread_id = b.thd_id limit 1; 

b)统计top 10的buffer pool占用内存的表

select * from innodb_buffer_stats_by_table order by pages desc limit 10;


Q:MySQL数据库磁盘io使用高,请问如何进行排查?

问题描述:通过系统能确定是数据库的io读写高,有哪些系统表或者sql联合起来可以把关键的sql定位出来?

答:mysql5.7版本为例,结合performance_schema来查看MySQL数据库的各种指标。相当于Oracle数据库中的各种性能视图,可以查看几乎所有的数据库状态。

IO的话,可以查看这张表:

performance_schema.file_instances:列出了文件I / O操作及其相关文件的工具实例

排查思路:

1、慢SQL排除

2、硬件问题-RAID降级,磁盘故障等排除

2、innodb_log、innodb_buffer_pool_wait相关配置和等待

3、IO相关参数配置

innodb_flush_method = O_DIRECT

innodb_file_per_table = 1

innodb_doublewrite = 1

delay_key_write

innodb_read_io_threads

innodb_read_io_threads

innodb_io_capacity

innodb_flush_neighbors


sync_binlog

主要关注:sync_binlog

建议:最好部署相关的监控平台或者对比历史性能记录,结合业务以及负载来分析。


3. 优化方法


Q:MySQL优化的常用方法有哪些?

答:

一、最常见是慢查询优化

1、打开慢查询记录,设置记录SQL的最短时间

2、使用pt工具,分类统计慢查询语句

3、针对执行次数多或者时间长的语句进行优化(索引优化、SQL改写、业务逻辑优化)

ps:也可以在系统表中,查看全表扫描多的表等

二、配置文件优化

1、内存使用量

2、各种方面写盘策略


Q:MySQL中执行计划如何解读?

问题描述:1:执行计划如何解读?

db2中按照从下往上,从左到右的顺序来解读

2:执行计划中需要关注的特殊标识有哪些?

例如:using where

using filesort

Using temporary

等等

答:

1、执行顺序,看ID列

id值相同执行顺序从上到下。

id值不同时id值大的先执行。

2、关注的特殊标识

SELECT_TYPE--执行查询类型,不同类型对应的

Type:访问类型,很重要

possible_keys:索引使用

关于explain输出参数,可参考官方文档:以MySQL5.7为例

https://dev.mysql.com/doc/refman/5.7/en/explain-output.html


Q:MySQL中关于表维护的操作(提升性能相关的)有哪些?

问题描述:MySQL中关于表维护的操作(提升性能相关的)有哪些?例如db2中的表重组,db2rbind 绑定包等操作

答:MySQL的表维护语句:

ANALYZE TABLE:更新表统计信息。执行该语句的时候innodb及myisam表会加上读锁,停止数据更新。该语句支持innodb,myisam及ndb表,针对myisam表,该语句等同myisamchk --analyze

OPTIMIZE TABLE:整理数据,表碎片

CHECK TABLE:用来检查数据库表和索引是否损坏

REPAIR TABLE:check table语句可以检查一个表中的的问题,若表或索引损坏,可以使用repair table语句尝试修正它


Q:业内有哪些mysql性能优化工具,欢迎大家帮忙推荐?

问题描述:有哪些工具可以帮助优化MySQL的?例如美团的sql advis工具,在建立索引方面提供建议

答1:SQL优化主要还是看经验和对慢查询梳理,美团工具有一定作用(看github好像2年没更新了)

https://github.com/Meituan-Dianping/SQLAdvisor

表结构规范可以用inception检查(闭源了,老的还能用)

配置文件优化,一般来说就几个参数需要优化,其他可以不动

https://github.com/major/MySQLTuner-perl

答2:以下工具可以参考:

pt-mysql-summary

pt-variable-advisor

pt-duplicate-key-checker

pt-deadlock-logger 

或者

tuning-primer.sh


4. 其他问题


Q:MySQL适用的场景是什么?

问题描述:MySQL有很多特性,不容易掌控。请问下MySQL适用的场景是什么?数据数量级在什么区间内?运维团队需要什么规模?是否需要有开发专门配合?灾备使用什么模式和工具?

答:不依赖存储过程、函数、触发器的传统oltp场景都适用

数据量建议单实例T级或以内

运维团队任何规模都可以,因为是一个相对轻量级的数据库

需要开发专门配合,毕竟语法和特性每个库都不一样

灾备使用MySQL各类的高可用方案即可,比如主从、mha、mgr等


Q:MySQL巡检优先关注哪些参数?

答:优先查看日志中的报错信息

然后查看监控系统中的历史数据(各类峰值,骤变值),报警信息

然后查看慢查询日志

深入可以看各类锁记录、等待事件等(需要开启统计,并且没有重启过)


Q:MySQL索引的创建时间怎么看?

答1:没有相关命令查看索引创建时间,最多在binlog等日志中查看

可以在mysql.innodb_index_stats查看最后更新时间

答2:SHOW INDEX FROM table_name [FROM db_name],这样子查看下,是不是有相关信息


如有任何问题,可点击文末阅读原文到社区原文下评论交流


 资料/文章推荐:

  • MySQL性能故障优化利器之索引优化

    http://www.talkwithtrend.com/Article/244357

  • MySQL诊断分析低效SQL方法

    http://www.talkwithtrend.com/Article/242995


欢迎关注社区 “mySQL”技术主题,将会不断更新优质资料、文章。地址:

http://www.talkwithtrend.com/Topic/3873


下载 twt 社区客户端 APP

与更多同行在一起

高手随时解答你的疑难问题

轻松订阅各领域技术主题

浏览下载最新文章资料


长按识别二维码即可下载

或到应用商店搜索“twt”


长按二维码关注公众号

*本公众号所发布内容仅代表作者观点,不代表社区立场

评论