翻阅《mysql 运维内参 》一书,摘取了一部分感兴趣的做下记录。 

Mysql sys schema

 

Mysql核心监控策略是performance schema。它在5.7中的改进,包含引入大量新加入的监控项,降低占用空间和负载,以入通过sys schema机制显著提升易用性。

监控方面performance schema提供了如下供能:

  • 元数据锁:可通过metadata_locks表了解元数据锁的信息。从5.7.3开始,如哪些会话拥有哪些元数据锁,哪些会话正在等待、哪些请求由于死锁被杀掉,或锁等待超时而被丢弃。
  • 进度跟踪:跟踪长时间操作的进度。可events_stages_current表来查看当前事件的进度信息。
  • 事务:监控服务与存储层事务的全部方面。从5.7.3开始,新增了events_transactions_current表,可通过setup_consumers、setup_instruments表打开事务监控,通过该表查询到当前事务的状态。如果线上数据库遇到undo log大量增长、数据库性能急剧下降的情况,可通过该表查询当前是否存在处于未提交状态的事务。如果发现的确有大量事务的state处于active,这时可以确定数据库有大量的事务未提交。
  • 内存使用:提供内存使用信息统计,有利于了解和调整服务器的内存消耗。从5.7.2开始,新增了内存有关的统计信息,分别从账号、访问主机、线程、用户及事件的角度统计了内存的使用状况。
  • 存储程序:存储过程、存储方法、事件调度器和表触发器的检测器。Setup_objects表中,新增了事件、函数、procedure、trigger的检测器。

 

Sys schema介绍

performance schema比较复杂,且与information_schema部分表有关联。5.7中新增了sys schema。它是由一系列对象组成的database schema,它本身不采集和存储信息,只是将performance schema与information_schema归纳为视图。通过视图定义可以看出数据来源处理过程。

它典型的调优和诊断用例,这些对象包括如下三个:

  • 将性能模式数据汇总到更易于理解的视图。
  • 诸如性能模式配置和生成诊断等操作的存储过程。
  • 用于查询性能模式配置并提供格式化服务的存储函数。

它提供摘要视图以回答诸如下面所列的常见问题。

  • 谁占了数据库服务器的所有资源;
  • 哪些主机对数据库服务器的访问量最大;
  • 实例上的内存都去哪里了?

 

Sys schema 重点视图与应用场景

  • 查看表的访问量
  • 冗余索引与未使用的索引检查
  • 表自增ID监控
  • 监控全表扫描的SQL语句
  • 查看实例消耗的磁盘IO

查看表的访问量

应用:如何查看问题快速定位是哪个业务引起的QPS上升,或上线新业务需要评估涉及表访问量的增长情况。

Mysql>select table_schema,table_name,sum(io_read_requests+io_write_requests) from ‘schema_table_statistics’;

Mysql> select table_schema,table_name,io_read_requests+io_write_requests as io_total from ‘schema_table_statistics’;

可以监控每张表访问量的变化情况。或监控某个库的访问量。如果某个库、某个表发生变化,DBA能及时知道每个表的访问情况。


冗余索引与未使用的索引检查

一般都会有索引使用率很低或者是冗余索引的情况,这些索引是完全没有必要建立的。它们不仅消耗磁盘空间,还影响db的性能,需要实时关注是否有该类索引的出现,出现时需要立即处理。

Mysql>select *  from sys.schema_redundant_indexs \G

Mysql>select *  from sys.schema_unused_indexs;

对于冗余的要及时清理,对长期未使用的索引,与业务方沟通是否以后有使用该索引的SQL语句等,如果没有或暂时不用的,可删除该索引,减少磁盘压力。

 

表自增ID监控

了解每个表的增量列的情况。可用schema_auto_increment_columns视图,就能很简单地查到每个表的自增量使用情况,可以精确到某个表的自增量情况。

Mysql>select * from ‘schema_auto_increment_columns’ \G

可以展示表的自增量列名、数据类型、当前使用量、最大值及使用率情况。可以监控此值,如果大了邮件报警。

监控全表扫描的SQL语句

Mysql>select * from sys.statements_with_full_table_scans where db=’test2’ \G

可看出执行次数、未使用索引次数。还可以通过总延迟计算每次消耗的时间,可针对每次消耗时间比较长的全表扫描的语句,进行优化。

查看实例消耗的磁盘IO

如果磁盘IO消耗大,需要知道在哪些数据库文件上消耗了大量的磁盘IO。如果能快速知道具体的文件消耗磁盘IO量,排查问题时就会简单很多。

Mysql>select file,avg_read+avg_write as avg_io from ‘io_global_by_file_by_bytes’

Order by avg_io desc limit 10;

可以通过这个查询大致了解磁盘IO消耗在哪里,哪些文件消耗的最多。可以此信息,对某些表、某些库进行针对性优化,提高DB性能。

 

本身performance的开启就有一定的性能损耗(可能10%)。

 

 

行之有效的延迟优化方法

  • 增加从库参数innodb_buffer_pool_size的值,可以缓存数据,减少由于转换导致的IO压力。
  • 增大参数innodb_log_file_size、innodb_log_files_in_group 的值,减少buffer pool的刷盘IO,提升写入性能。
  • 修改参数innodb_flush_method 为O_DIRECT,提升写入性能(在ssd下,或者磁盘IO能力强的时候推荐使用)。
  • 如果可以的话,把从库binlog关掉,或者关掉参数log_slave_updates。
  • 修改参数innodb_flush_log_at_trx_commit为0或2。
  • 如果binlog没有关掉,修改sync_binlog参数为0或一个很大的数,减少磁盘IO压力。
  • 如果binlog_format为row模式,并且被修改表没有主键,则需要加上主键。
  • 如果binlog_format为row模式,则可以在从库中删掉一些不必要的索引(同步完毕之后再加上)
  • 了解清楚写库上的操作内容,适当地在从库中预热一下数据,可以减少在复制时等待的时间。
  • 如果binlog_format为statement模式,或存在DDL复制,则可以将tmpdir参数改到内存中,比如/dev/shm。
  • 修改参数master_info_repository、relay_log_info_repository为table,减少直接IO导致的磁盘压力。
  • 将从库的服务迁走,这时指简单的处理。
  • 升级硬件
  • 如是mysql5.6,并且实例中数据库比较多,写入比较均匀,可以打开多线程复制。
  • 升级成5.7

 

Mysql常用的参数

1)         General_log建议正常服务时,关闭,费资源也影响效率。如果需要分析问题,可打开截取一段时间的日志,帮助定位。

2)         Query_cache_size用来缓存SQL语句文本和对应查询缓存空间。如果相应表没有变化,下次再碰到完全一致的SQL时,则跳过一切解析和查询,直接返回结果。这对某些情况合适。但如果表变化频繁,SQL也是动态生成的,则由于要不断更新cache中的内容,并且这个时候锁粒度很大,反而会成为瓶颈。很多情况,会关掉此选项,设置为0.

3)         Sort_buffer_size排序时,如果用不到索引就会在内部临时进行排序,这时会用到排序的buffer。如果此参数设置过小,排序过程中会把结果写入到物理磁盘,严重影响效率。但,它是一个session变量,每个sessionet 用到时都会申请一块这么大的内存,如果太大可能会耗尽内存,导致服务器OOM。大小要根据实际情况,灵活设置。类似的join_buffer_size。

4)         Tmp_table_size在group by或distinct时,如果SQL语句用不到索引,就会使用内部临时表记录中间状态。如果不够大,则mysql会自动使用物理磁盘,这会对查询性能造成很大的影响,增加此参数可降低这种情况的发生。

5)         Innodb_buffer_pool_sizeinnodb最重要的缓存,用来缓存innodb索引页面、undo页面及其他一些辅助数据。它的大小是影响性能的重要因素,基本上各种文档都会要求在内存允许的情况下尽可能地配置大一些,官方建议配置物理内存的50%-70%。

6)         Innodb_buffer_pool_instances它可以把一整块buffer pool分割为多快内存空间,每个空间独立管理自己的空闲链表、刷新链表、LRU及其他数据结构。大大增加了并发性,能更有效利用缓存。

7)         Innodb_log_file_size和innodb_log_files_in_group它俩结合,决定了redo空间的大小。Redo空间越大,可存储的增量更新日志越大,有效降低了buffer pool脏页面被淘汰的速度,同时减少了checkpoint的次数,降低了磁盘IO转换率,从而提升db的写入效率。不过也有可能会导致数据库异常退出时,恢复时间被拉长。

8)         Innodb_old_blocks_pct和innodb_old_blocks_time它俩控制buffer pool中缓存数据的过期和移动行为,二者结合配置,可以优化一些全表扫描带来的大规模更新buffer问题。

9)         Innodb_numa_interleave:mysql服务器很多时候会出现内存被交换到swap的情况,这时性能会急剧下降。但当我们去查看服务情况的时候,常会发现实际个操作系统还有很多空闲内存。在5.7.9后,通过这个参数可避免这个问题。它在分配内存时,会把numa的策略设置为MPOL_INTERLEAVE。这个需要大支持numa的系统上编译MYSQL才可。

10)     Innodb_automic_lock_mode:在innodb有自增列的情况下,在插入数据时,会自动产生自增值,这个参数是控制自增值生成的方式。目前有三个选项,0,1,2.其实这是个枚举。

11)     Innodb_flush_method:innodb刷数据和日志到磁盘文件的方式,默认为NULL,但其实如果是在类unix系统上,默认为fsync,在windows系统上默认为async_unbuffered。这里要说的是,它还有个可能的值是O_DIRECT,在使用SSD或PCIE类型的存储时,可以设置为O_DIRECT,底层调用directio(),直接修改写入磁盘,以提升性能。

12)     Innodb_doublewrite:关于innodb的两次写。这里要强调的是如果底层存储是支持原子写的,则可以关闭两次写,以提升效率。

13)     Innodb_io_capacity:innod有个后台线程在不断做flush操作,影响这个操作频率的就是innodb_io_capacity这个参数,如果碰到系统因为后台flush操作而产生周期性性能下降的情况,特别是在使用SSD设备时,可以适当提高这个参数的值,以加速flush的频率。

14)     Innodb_thread_concurrency:在并发量大的实例上,增加这个值,可以降低innodb在并发线程之间切换的开销,以增加系统的并发吞吐量。

15)     Innodb_flush_log_at_trx_commit: Innodb刷日志的方式。0性能最好,但最不安全,不推荐。1最安全,但性能最差。如果磁盘足够好,可弥补性能损失的话,还是建议为1。可根据实际情况选择设置为2.

16)     Sync_binlog: mysql同步到磁盘的方式。1最安全,性能最差。0性能最好,最不完全。如果磁盘足够好,可弥补性能损失的话,还是建议为1。

17)     Binlog_format: 日志格式,在5.7.7后默认为row。在很多场景下都建议的选项。

18)     Binlog_order_commits:事务在提交时写入binlog的顺序。如果打开,可以保证事务都以相同的顺序写入二进制文件,如果关闭则可以提升性能。根据实际情况看。

19)     Tx_isolation: mysql隔离级别。Read uncommitted、read committed、read peatableread、serializable这4级级别,级别越来越严,性能越来越差。推荐与binlog_format结合设置。推荐级别为read committed,这在保证性能的前提下,同时设置binlog_format=row,确认通过binlog同步数据主从库的一致性,兼顾到安全,满足大多数业务的需求。

20)     Slave_parallel_workers:进行多线程复制时,如果设置此参数为非0值,则可打开多线程并发执行回放日志的操作,以提升slave的同步性能。


 

关于CPU

Mysql在执行单个SQL语句时,在底层只能用一个CPU,所以要想提升SQL的执行效率,在考虑CPU时,最好选择主频高的,这有利于加速单条SQL语句的执行效率。在极端情况下,如电商秒杀这类的密集业务,并发需求很大,这时,并发执行的SQL需求很大,要保证在短时间内有巨大的吞吐量,就需要选择核心数多的CPU。

 

关于内存

内存是解决磁盘IO能力不足,提效提升性能的利器。大部分情况下,增加MYSQL主机内存,并配置到数据库引擎中去,可有效提升性能。例外就是,即使配置的比实际用的大很多,也未达到预期性能,这时就需要考虑从SQL语句性能优化、表设计的合理性等软件因素去寻找。

Mysql cluster的存储引擎是NDB,它是基于内存存储的。NDB是自动切分到分布式存储的,并且都是把数据存在内存中,其数据的存取效率很难提升,性能影响主要来于SQL语句中查询逻辑的处理和数据的集合合并,如果盲目增加集群机器,可能会造成重新分布分片存储的情况,并且分布更加稀疏,合并数据时需要更多资源。

选内存时要注意频率跟主要CPU频率的匹配,二者一致才能发挥最大处理能力。

 

云数据库的性能优化覆盖多个子系统,如:

1、  接入集群的性能优化

它一般是屏蔽MYSQL服务进程,常有三种功能:路由、HA和防火墙安全。通常接入节点的实现是通过用户态的中间件来实现,复杂点可能会考虑到SQL语句解析。相比单纯节点,接入节点常会损失20%左右性能。

2、  实例集群的性能优化

就是mysql集群,包含两方面:MYSQL引擎本身优化、复制优化。

3、  数据库存储优化