按照从大到小,从主要到次要的形式,分析 mysql 性能优化点,达到终优化的效果。
  利用 mindmanger 整理了思路,形成如下图,每个点在网上都能找到说明,并记录下。形成了优化的思路:

  1 连接 Connections
  经常会遇见”mysql: error 1040: too many connections”的情况,一种是访问量确实很高,mysql服务器抗不住,这个时候要考虑增加从服务器分散读压力,另外一种情况是mysql配置文件中max_connections值过小:
  mysql> show variables like ‘max_connections‘;
  +—————–+——-+
  | variable_name  | value |
  +—————–+——-+
  | max_connections | 256  |
  +—————–+——-+
  这台mysql服务器大连接数是256,然后查询一下服务器响应的大连接数:
  mysql> show global status like ‘max_used_connections‘;
  mysql服务器过去的大连接数是245,没有达到服务器连接数上限256,应该没有出现1040错误,比较理想的设置是
  max_used_connections / max_connections * ≈ 85%
  大连接数占上限连接数的85%左右,如果发现比例在10%以下,mysql服务器连接数上限设置的过高了。
  2 线程 Thread
  mysql> show global status like ‘thread%‘;
  +——————-+——-+
  | variable_name   | value |
  +——————-+——-+
  | threads_cached  | 46  |
  | threads_connected | 2   |
  | threads_created | 570  |
  | threads_running | 1    |
  +——————-+——-+
  如果我们在mysql服务器配置文件中设置了thread_cache_size,当客户端断开之后,服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)。
  threads_created表示创建过的线程数,如果发现threads_created值过大的话,表明mysql服务器一直在创建线程,这也是比较耗资源,可以适当增加配置文件中thread_cache_size值,
  查询服务器 thread_cache_size 配置:
  mysql> show variables like ‘thread_cache_size‘;
  +——————-+——-+
  | variable_name   | value |
  +——————-+——-+
  | thread_cache_size | 64   |
  +——————-+——-+
  示例中的服务器还是挺健康的。
  3 缓存 cache
  3.1 文件打开数

  mysql> show global status like ‘open_files‘;
  +—————+——-+
  | variable_name | value |
  +—————+——-+
  | open_files   | 1410  |
  +—————+——-+
  mysql> show variables like ‘open_files_limit‘;
  +——————+——-+
  | variable_name   | value |
  +——————+——-+
  | open_files_limit | 4590 |
  +——————+——-+
  比较合适的设置:open_files / open_files_limit * <= 75%
  3.2 数据表
  3.2.1 打开数 open_tables

  mysql> show global status like ‘open%tables%‘;
  +—————+——-+
  | variable_name | value |
  +—————+——-+
  | open_tables  | 919  |
  | opened_tables | 1951 |
  +—————+——-+
  open_tables: 打开表的数量
  opened_tables: 打开过的表数量
  如果 opened_tables 数量过大,说明配置中 table_cache(5.1.3之后这个值叫做table_open_cache)值可能太小,我们查询一下服务器table_cache值:
  mysql> show variables like ‘table_cache‘;
  +—————+——-+
  | variable_name | value |
  +—————+——-+
  | table_cache    | 2048  |
  +—————+——-+
  比较合适的值为:
  open_tables / opened_tables * >= 85%
  open_tables / table_cache * <= 95%
  3.2.2 临时表 tmp_table
  mysql> show global status like ‘created_tmp%‘;
  +————————-+———+
  | variable_name      | value   |
  +————————-+———+
  | created_tmp_disk_tables | 21197  |
  | created_tmp_files    | 58    |
  | created_tmp_tables   | 1771587 |
  +————————-+———+
  每次创建临时表,created_tmp_tables 增加,如果是在磁盘上创建临时表,created_tmp_disk_tables也增加,created_tmp_files表示mysql服务创建的临时文件文件数,比较理想的配置是:
  created_tmp_disk_tables / created_tmp_tables * <= 25%
  比如上面的服务器 created_tmp_disk_tables / created_tmp_tables * = 1.20%,应该相当好了。我们再看一下mysql服务器对临时表的配置:
  mysql> show variables where variable_name in (‘tmp_table_size‘, ‘max_heap_table_size‘);
  +———————+———–+
  | variable_name    | value      |
  +———————+———–+
  | max_heap_table_size | 268435456 |
  | tmp_table_size    | 536870912 |
  +———————+———–+
  只有 256mb 以下的临时表才能全部放内存,超过的会用到硬盘临时表。
  3.2.3 表锁情况
  mysql> show global status like ‘table_locks%‘;
  +———————–+———–+
  | variable_name     | value    |
  +———————–+———–+
  | table_locks_immediate | 490206328 |
  | table_locks_waited  | 2084912  |
  +———————–+———–+
  table_locks_immediate 表示立即释放表锁数,
  table_locks_waited 表示需要等待的表锁数,
  如果 table_locks_immediate / table_locks_waited > 5000,好采用innodb引擎,因为innodb是行锁而myisam是表锁,对于高并发写入的应用innodb效果会好些。
  示例中的服务器 table_locks_immediate / table_locks_waited = 235,myisam足够了。
  3.2.4 表扫描情况
  mysql> show global status like ‘handler_read%‘;
  +———————–+————-+
  | variable_name     | value     |
  +———————–+————-+
  | handler_read_first  | 5803750   |
  | handler_read_key   | 6049319850 |
  | handler_read_next  | 94440908210 |
  | handler_read_prev  | 34822001724 |
  | handler_read_rnd   | 405482605  |
  | handler_read_rnd_next | 18912877839 |
  +———————–+————-+
  各字段解释参见 http://hi.baidu.com/thinkinginlamp/blog/item/31690cd7c4bc5cdaa144df9c.html ,调出服务器完成的查询请求次数:
  mysql> show global status like ‘com_select‘;
  +—————+———–+
  | variable_name | value      |
  +—————+———–+
  | com_select     | 222693559 |
  +—————+———–+
  计算表扫描率:
  表扫描率 = handler_read_rnd_next / com_select
  如果表扫描率超过 4000,说明进行了太多表扫描,很有可能索引没有建好,增加 read_buffer_size 值会有一些好处,但好不要超过8mb。
  3.3 key_buffer_size
  key_buffer_size是对myisam表性能影响大的一个参数,下面一台以myisam为主要存储引擎服务器的配置:
  mysql> show variables like ‘key_buffer_size‘;
  +—————–+————+
  | variable_name  | value    |
  +—————–+————+
  | key_buffer_size | 536870912 |
  +—————–+————+
  分配了 512mb 内存给 key_buffer_size ,我们再看一下 key_buffer_size 的使用情况:
  mysql> show global status like ‘key_read%‘;
  +————————+————-+
  | variable_name     | value     |
  +————————+————-+
  | key_read_requests   | 27813678764 |
  | key_reads       | 6798830    |
  +————————+————-+
  一共有 27813678764个 索引读取请求,有 6798830个 请求在内存中没有找到直接从硬盘读取索引,计算索引未命中缓存的概率:
  key_cache_miss_rate = key_reads / key_read_requests *
  比如上面的数据,key_cache_miss_rate为0.0244%,4000个索引读取请求才有一个直接读硬盘,已经很bt了,key_cache_miss_rate在0.1%以下都很好(每1000个请求有一个直接读硬盘),如果key_cache_miss_rate在0.01%以下的话,key_buffer_size分配的过多,可以适当减少。