mysql-监控和优化-总结版

mysql-监控和优化-总结版

20120618


  写在前面,本文是笔者的一个学习过程中的笔记,也是工作中的一个总结,其中一部分参考了网友的一些资料,但大多数(尤其在优化设置方面)是工作中实践过的。注:其中示例并不全都是实际生产中的结果,有些是测试机的result。

  可依照第三部分开始的setting和status对你的database server来走一遍,当然时机你来选,或许有收获,如有不同观点,与本人联系。


*************************************
一 监控和优化什么
  性能监控和优化,是指监控那些可以反映出数据库的性能的指标:

  1)CPU,内存和IO在操作系统层面的使用情况;
     sysstat 来收集数据库服务器操作系统层面的CPU,内存,IO 等指标;

  2)查询响应时间;
     启用 MySQL 慢查询记录功能来监视和分析;

  3)吞吐量;
     a. 查询cache:    执行SQL语句 show status like ‘qcache%’ 收集指标值。
     b. 表缓存:    MySQL 表对应于磁盘上的文件,表缓存就是文件缓存。
        执行SQL语句 show status like ‘open%tables’ 来收集指标值。
     c. 线程缓存:    启用了线程缓存后,一个线程在其生命周期中就可以服务多个连接,从而加速MySQL初始连接速度。
        执行SQL语句 show status like ‘threads%’ 来收集相关指标值。
     d. 关键字段(key)缓存:跟缓存表一样,缓存关键字段同样可以提高查询效率。
        执行SQL语句 show status like ‘%key_read%’ 来收集相关指标值。
     e. 临时表:这里的临时表,指的是MySQL内部临时存放需要进一步处理的数据所使用的表,不是我们在存储过程中自定义的临时表。如果临时表放不下需要临时存放的数据,MySQL会使用磁盘来存放,从而降低性能。
        执行SQL语句 show status like ‘created_tmp%’ 来收集相关指标值。
     f. 排序区:    当MySQL要执行排序操作的时候,它会使用排序区,如果指定的内存排序区放不下需要排序的数据,MySQL会使用磁盘来存放,从而降低性能.
        执行SQL语句 show status like ’sort%’ 来收集相关指标值。
     g. 全表扫描情况:通常情况下,对大表执行全表扫描很低效,应该尽量避免。
        执行SQL语句 show status like ‘com_select%’ 和 show status like handler_read_rnd_next%’ 来收集相关指标值。

  4)各种 Cache 命中率;

******************************************
二 确定什么时间/段的信息

  我们收集数据库在各个具有代表性的时间段的基准值,在各种具有代表性的负载时的基准值,尤其是在峰值期间的基准值。收集基准值的方法就是前面讲述的用来获得性能指标值的方法。

  show global status;
  可以列出MySQL服务器运行各种状态值

  show variables;
  查询MySQL服务器配置信息语句

*********************************************
三 通用的设置和优化

*********************************************

  说明,下边的一些设置和分析,是相互参考的,从status来看是否需要优化或设置,从设置的值对比status来看是否合理或需重配置。


3.1 日志设置
  说明:这是针对io的设置和优化;日志有二进制日志、错误日志、慢日志和通用日志(查询日志)
  原则:只打开必要的日志,因为开启日志会带来性能的部分影响

3.1.1 二进制日志的设置
  (1)  binlog是否开启
  开启 log-bin 会使性能下降 46%,无必要的情况下,不用开启,注释掉log-bin和server-id
  show variables where variable_name like '%log%bin%' or variable_name like 'server%id';
  log-bin = mysql.bin
  server-id = 99531

  (2) binlog的缓存和刷新设置
  show variables like '%binlog%';
    +-----------------------------------------+----------------------+
    | binlog_cache_size                       | 32768                |
    | binlog_direct_non_transactional_updates | OFF                  |
    | binlog_format                           | STATEMENT            |
    | binlog_stmt_cache_size                  | 32768                |
    | innodb_locks_unsafe_for_binlog          | OFF                  |
    | max_binlog_cache_size                   | 18446744073709547520 |
    | max_binlog_size                         | 1073741824           |
    | max_binlog_stmt_cache_size              | 18446744073709547520 |
    | sync_binlog                             | 0                    |
    +-----------------------------------------+----------------------+

  说明:
  (a) binlog_cache_size: 事务过程中容纳二进制日志sql语句的缓存大小,该值是为每个client分配的内存大小;系统中如果经常出现多语句事务的话,可以增加该值;设置依据:show status like 'binlog_cache%'; 查看其中的使用情况,如果binlog_cache_disk_use不为0或较大,则可以增加本设置值;
  (b) max_binlog_cache_size: 和binlog_cache_size对应,表示binlog能够使用的最大cache内存大小,该值默认很大,一般不用重设;
  (c) max_binlog_size: binlog日志文件最大值
  (d) sync_binlog: 表示binlog_cache刷新的时机,该值比较重要,会对性能产生较大影响;
      取0,事务提交后,binlog_cache的信息刷新到硬盘不由mysql来控制,而是由操作系统自行决定;或cache满了后才同步到磁盘;
      取n,每进行n次事务后,mysql进行一次fsync之类的同步指令来将binlog_cache中的数据刷新到磁盘;设置为1是最安全但性能损耗最大;

  (3) binlog的复制相关设置
  以下这些值会决定io线程的io量和日志生成的多少以及传输的流量;slave的相关设置还可以减少slave的sql线程的日志应用量;
  对于master:
    binlog_do_db和binlog_ignore_db
  对于slave:
    replicate_do_db, replicate_ignore_db
    replicate_do_table, replicate_ignore_table
    replicate_wild_do_table, replicate_ignore_table

  (4) 查看status
  show status like 'binlog_cache%';
    +-----------------------+-------+
    | Binlog_cache_disk_use | 0     |
    | Binlog_cache_use      | 0     |
    +-----------------------+-------+
  说明:如果Binlog_cache_disk_use不为0则binlog_cache可能不够;


3.1.2 慢日志的设置
  (1) 查看是否开启了慢慢日志
    show variables like '%quer%';
    +------------------------------+---------------+
    | log_queries_not_using_indexes| OFF           |
    | long_query_time              | 2.000000      |
    | slow_query_log               | ON            |
    | slow_query_log_file          | slowquery.log |
    +------------------------------+---------------+

  (2) 开启慢查询监控
  slow query log功能对性能有一点影响,由于数据量较小,对io的影响较小,主要是需要计算执行时间,对cpu的消耗;
  慢查询时间不宜设置过长,否则意义不大,最好在5秒以内,如果你需要微秒级别的慢查询,可以考虑给MySQL打补丁http://www.percona.com/docs/wiki/release:start,记得找对应的版本。

  打开慢查询日志可能会对系统性能有一点点影响,如果你的MySQL是主-从结构,可以考虑打开其中一台从服务器的慢查询日志,这样既可以监控慢查询,对系统性能影响又小。

  方法一,配置文件修改, 然后重新启动MySQL服务

    slow_query_log = 1
    slow_query_log_file  = /usr/var/slowquery.log
    long_query_time = 10    

    注,5.1 为 log-slow-queries = /usr/var/slowquery.log | OFF
    
  方法二,设置gloabl|session变量

    set global slow_query_log = 1;
    set global slow_query_log_file  = /usr/var/slowquery.log
    set global long_query_time = 10;
    
    注,5.1 为 set global log_slow_queries = 1;

  (3) 监控慢查询status
    show global status like '%slow%';
    +---------------------+-------+
    | Slow_queries        | 4148  |
    +---------------------+-------+
  说明:系统显示有4148个慢查询,你可以分析慢查询日志,找出有问题的SQL语句,

  (4) 分析工具和方法,具体见专题
  mysqldumpslow
  profileing

3.1.3 通用日志
  一般不需要打开,可以动态打开查看

*********************************************
3.2 查询缓存设置(query cache)

3.2.1 关于query_cache的配置:
  show variables like '%query_cache%';
    +------------------------------+-----------+
    | have_query_cache             | YES       |
    | query_cache_limit            | 2097152   |
    | query_cache_min_res_unit     | 4096      |
    | query_cache_size             | 203423744 |
    | query_cache_type             | ON        |
    | query_cache_wlock_invalidate | OFF       |
    +------------------------------+-----------+

  说明:
    have_query_cache:    是否支持query_cache
    query_cache_limit:    query cache存放的单条query最大result set,默认1M;超过此大小的查询将不缓存
    query_cache_min_res_unit:缓存块的最小大小;这个配置是一柄”双刃剑”,默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小数据查询,就容易造成内存碎片和浪费。
    query_cache_size:    查询缓存大小
    query_cache_type:    缓存类型,决定缓存什么样的查询,示例中表示不缓存 select sql_no_cache 查询
    query_cache_wlock_invalidate:针对MYISAM引擎,设置当有write lock在某个table上时,其他客户的读请求是要等待lock释放资源后再查询还是操作时,如果查询在query cache中,是否返回cache结果还是等写操作完成再读表获取结果。

    另外还有一个设置参数,query_prealloc_size, 查询分析器预分配缓存;对大数据库来说,可预先分配的大一点;
    
  建议:
    如果cache的result set一般都很小的话,可以将query_cache_min_res_unit调小一些,避免内存浪费;
    query_cache_limit 应大于 query_cache_min_res_unit 的大小;
 
3.2.2 查看query cache的status
  show global status like 'qcache%';
    +-------------------------+-----------+
    | Qcache_free_blocks      | 22756     |
    | Qcache_free_memory      | 76764704  |
    | Qcache_hits             | 213028692 |
    | Qcache_inserts          | 208894227 |
    | Qcache_lowmem_prunes    | 4010916   |
    | Qcache_not_cached       | 13385031  |
    | Qcache_queries_in_cache | 43560     |
    | Qcache_total_blocks     | 111212    |
    +-------------------------+-----------+

  说明:
    Qcache_free_blocks:缓存中剩余的内存块的个数。数目大说明可能有碎片。FLUSH QUERY CACHE会对缓存中的碎片进行整理,从而得到一个空闲块。
    Qcache_free_memory:缓存中剩余的内存大小,这个值提示我们当前query cache内存大小是否足够。
    Qcache_hits:        多少次命中cache,每次查询在缓存中命中时就增大
    Qcache_inserts:    多少次未命中然后插入;每次插入一个查询时就增大。命中次数除以插入次数就是不中比率。
    Qcache_lowmem_prunes:多少条query被清除出cache;缓存出现内存不足并且必须要进行清理以便为更多查询提供空间时会进行这个操作。这个数字最好长时间来看;如果这个数字在不断增长,就表示可能碎片非常严重,或者内存很少。(上面的 free_blocks和free_memory可以告诉您属于哪种情况)
    Qcache_not_cached:    不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句或者用了now()之类的函数。
    Qcache_queries_in_cache:当前缓存中query数量    。
    Qcache_total_blocks:缓存中块的数量。

    查询缓存碎片率 = Qcache_free_blocks / Qcache_total_blocks * 100%
    如果查询缓存碎片率超过20%,可以用FLUSH QUERY CACHE整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话。

    查询缓存利用率 = (query_cache_size – Qcache_free_memory) / query_cache_size * 100%
    查询缓存利用率在25%以下的话说明query_cache_size设置的过大,可适当减小;查询缓存利用率在80%以上而且Qcache_lowmem_prunes > 50的话说明query_cache_size可能有点小,要不就是碎片太多。

    查询缓存命中率 = Qcache_hits / (Qcache_hits – Qcache_inserts)
    示例服务器 查询缓存碎片率 = 20.46%,查询缓存利用率 = 62.26%,查询缓存命中率 = 1.94%,命中率很差,可能写操作比较频繁吧,而且可能有些碎片。
*********************************************
3.3 连接相关的设置

3.3.1 禁用 dns 解析
  查看 show variables like '%name-resolve%';
  设置 skip-name-resolve

3.3.2 连接数的设置
  show variables like 'max%connections';
    +----------------------+-------+
    | max_connections      | 256   |
    | max_user_connections | 0     |
    +----------------------+-------+
  说明
    max_connections        影响并发处理能力,一般来说只要主机性能允许,尽量设得大一点;  经常会遇见”MySQL: ERROR 1040: Too many connections”的情况,一种是访问量确实很高,MySQL服务器抗不住,这个时候就要考虑增加从服务器分散读压力,另外一种情况是MySQL配置文件中max_connections值过小:
    max_user_connections 针对单个用户的连接限制,这个设置依赖于应用程序的连接用户数;

  查看status
  show global status like '%connections';
    +----------------------+-------+
    | Connections          | 2     |
    | Max_used_connections | 1     |
    +----------------------+-------+

  得出设置建议
    MySQL服务器过去的最大连接数是245,没有达到服务器连接数上限256,应该没有出现1040错误;
    比较理想的设置是:Max_used_connections / max_connections  * 100% ≈ 85%
    最大连接数占上限连接数的85%左右,如果发现比例在10%以下,MySQL服务器连接数上限设置的过高了。
 
3.3.3 消息缓冲区和传输量设置
  show variables like 'net_buffer_length';
    +-------------------+-------+
    | net_buffer_length | 16384 |
    +-------------------+-------+
  show variables like 'max_allowed_packet';
    +--------------------+----------+
    | max_allowed_packet | 16777216 |
    +--------------------+----------+

  说明:
    net_buffer_length    网络包传输中,传输消息之前的消息缓冲区(net buffer)初始化大小,默认为16K;只有当我们的消息都很大时才会需要把此值调大;
    max_allowed_packet    这个参数与net_buffer_length 相对应,是net buffer的最大值,允许的一次消息传输量的最大值;

3.3.4 连接等待队列设置
  show variables like 'back_log';
    +---------------+-------+
    | back_log      | 50    |
    +---------------+-------+
  back_log            在mysql的连接请求等待队列中允许存放的最大连接请求数;连接请求等待队列,指某一时刻客户端的连接请求数量过大时,未分配到连接线程的请求存放在一个等待队列中;一般来说,当系统存在瞬时的大量连接请求时,须注意该值的设置,而这个值也受限于os级别的监听队列数的限制;

3.3.5 thread_cache设置
  机制:mysql为了提高客户端请求创建连接的这个过程的性能,实现了一个thread cache池,将空闲连接线程存放在其中,而不是完成请求后就销毁;这样当有新连接请求时,可从cache中取出空闲的连接线程来用,没有的话才创建新连接线程;在一个连接变化很快的繁忙服务器上,对线程进行缓存便于以后使用可以加快最初的连接。

  查看设置
  show variables like 'thread%';
    +--------------------+---------------------------+
    | thread_cache_size  | 64                         |
    | thread_concurrency | 8                         |
    | thread_handling    | one-thread-per-connection |
    | thread_stack       | 196608                    |
    +--------------------+---------------------------+

  说明:
    thread_cache_size:thread cache池中可存放的连接线程数;在短连接的应用系统中,该值应相对大一些,不应该小于实际并发连接请求数;在长连接的应用中,设大点虽不像短连接系统那样明显,但也有好处;
    thread_stack: 每个连接线程被创建时分配的内存大小;默认192KB,一般不须调整该值,太小会影响客户端请求的query内容的大小;

  查看status:
  show global status like 'Thread%';
    +-------------------+-------+
    | Threads_cached    | 46    |
    | Threads_connected | 2     |
    | Threads_created   | 230   |
    | Threads_running   | 1     |
    +-------------------+-------+
  show global status like '%connections';
    +----------------------+-------+
    | Connections          | 302    |
    | Max_used_connections | 20    |
    +----------------------+-------+

  设置建议:
    Threads_created表示创建过的线程数,如果发现Threads_created值过大的话,表明MySQL服务器一直在创建线程,这也是比较耗资源,可以适当增加配置文件中thread_cache_size值;
    连接的thread cache命中率:( Connections - Threads_created ) / Connections,即通过cache取得连接线程的次数与总连接次数的比率;一般来说,查看一段时间的该计算值,应保持在90%左右甚至更高,否则thread_cache_size设置太小;

3.3.6 table_cache/table_open_cache设置
  机制:
    每个表都可以表示为磁盘上的一个文件,必须先打开,后读取。
    每个线程都是独立的打开自己需要的表的文件描述符,而不是通过共享已经打开的表的文件描述符;
    对MyISAM,每个客户端线程打开任何一个数据文件都需要打开一个文件描述符,对于索引文件可以共享同一个索引文件的描述符;
    对Innodb,如果是共享表空间则打开的文件描述符比较少,对于独立表空间则会较多;
    此外,临时文件也需要文件描述符,会占用open_files_limit的设置限额;

    而table cache机制就是为了解决打开表文件描述符的问题,和thread cache机制相似,当有新请求打开表时,先从cache中获取,这样就加快了从文件中读取数据的过程;

  查看设置
    show variables like '%table%cache%';
    +------------------------+-------+
    | Variable_name          | Value |
    +------------------------+-------+
    | table_definition_cache | 256   |
    | table_open_cache       | 1024  |
    +------------------------+-------+

  说明:
  table_open_cache 意义即缓存的表数量,注意5.1.3之前为table_cache。

  设置建议:
  table_open_cache = max_connections * N
  其中N为单个query语句所包含的最多table数量,这样的值实际是个设置的极值,因为正常下连接数并不是max_connections;

  查看status:
  show global status like 'open%table%';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | Open_table_definitions   | 34    |
    | Open_tables              | 919   |
    | Opened_table_definitions | 1     |
    | Opened_tables            | 1951  |
    +--------------------------+-------+

  说明:
    Open_tables    表示当前打开表的数量,
    Opened_tables  表示已经打开过的表的数量,如果Opened_tables数量过大,说明table_open_cache值可能太小
    理想的情况应该是:
    Open_tables / Opened_tables  * 100% >= 85%
    Open_tables / table_open_cache * 100% <= 95%

3.3.7 打开文件数设置
  查看设置:
  show variables like 'open_files_limit';
    +------------------+-------+
    | open_files_limit | 4590  |
    +------------------+-------+

  查看status:
  show global status like 'open_files';
    +---------------+-------+
    | Open_files    | 1410  |
    +---------------+-------+
  比较合适的设置:
    Open_files / open_files_limit * 100% <= 75%

3.3.8 临时表和内存表设置
  机制:
    临时表可以在更高级的查询中使用,其中数据在进一步进行处理(例如 GROUP BY 字句)之前,都必须先保存到临时表中;理想情况下,在内存中创建临时表。但是如果临时表变得太大,就需要写入磁盘中。

  查看设置:
    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以下的临时表才能全部放内存,超过的就会用到硬盘临时表。

  查看status:
    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 * 100% <= 25%

    比如上面的服务器Created_tmp_disk_tables / Created_tmp_tables * 100% = 1.20%,应该相当好了。

*********************************************
3.4 几个buffer的设置
3.4.1 sort_buffer_size
  机制:
    系统中对数据进行排序的时候使用的buffer,该值是针对单个thread的,可用来提高order by或group by的处理性能;默认为2MB;
    当 MySQL 必须要进行排序时,就会在从磁盘上读取数据时分配一个排序缓冲区来存放这些数据行。如果要排序的数据太大,那么数据就必须保存到磁盘上的临时文件中,并再次进行排序。

  查看:
    show variables like 'sort%';
    +------------------+---------+
    | sort_buffer_size | 8388608 |
    +------------------+---------+

  查看status
    show global status like 'sort%';
    +-------------------+------------+
    | Variable_name     | Value      |
    +-------------------+------------+
    | Sort_merge_passes | 29         |
    | Sort_range        | 37432840   |
    | Sort_rows         | 9178691532 |
    | Sort_scan         | 1860569    |
    +-------------------+------------+

  各项意义:
    Sort_merge_passes 排序算法已经执行的合并的数量。如果这个变量值较大,应考虑增加sort_buffer_size系统变量的值。
    Sort_range   在范围内执行的排序的数量。
    Sort_rows    已经排序的行数。
    Sort_scan    通过扫描表完成的排序的数量。

    Sort_merge_passes 包括两步。MySQL 首先会尝试在内存中做排序,使用的内存大小由系统变量 Sort_buffer_size 决定,如果它的大小不够把所有的记录都读到内存中,MySQL 就会把每次在内存中排序的结果存到临时文件中,等 MySQL 找到所有记录之后,再把临时文件中的记录做一次排序。这再次排序就会增加 Sort_merge_passes。实际上,MySQL 会用另一个临时文件来存再次排序的结果,所以通常会看到 Sort_merge_passes 增加的数值是建临时文件数的两倍。因为用到了临时文件,所以速度可能会比较慢,增加 Sort_buffer_size 会减少 Sort_merge_passes 和 创建临时文件的次数。但盲目的增加 Sort_buffer_size 并不一定能提高速度,见 How fast can you sort data with MySQL?(引自http://qroom.blogspot.com/2007/09/mysql-select-sort.html,貌似被墙)

    另外,增加read_rnd_buffer_size(3.2.3是record_rnd_buffer_size)的值对排序的操作也有一点的好处,参见:http://www.mysqlperformanceblog.com/2007/07/24/what-exactly-is-read_rnd_buffer_size/

3.4.2 join_buffer_size
  机制:
    join是all, index, rang或index_merge时使用的buffer;这际这种join被称为full join,参与join的每个表都需要一个join buffer;
    该值是针对单个thread的

  查看设置:
    show variables like 'join%';
    +------------------+---------+
    | join_buffer_size | 8388608 |
    +------------------+---------+

3.4.3 read_buffer_size,read_rnd_buffer_size
  注意:
    由于innodb使用不同的buffer机制,因此该值并不针对innodb,而是主要针对MyISAM的;

  机制:
    mysql有两种读取数据文件的缓冲区,一种是sequential scan(全表扫描)方式,另一种是random scan(索引扫描)方式;
    每次对数据文件的访问都需要从磁盘上读物理文件,mysql分配一些内存来读取表。理想情况下,索引提供了足够多的信息,可以只读入所需要的行,但是有时候查询(设计不佳或数据本性使然)需要读取表中大量数据。要理解这种行为,需要知道运行了多少个 SELECT 语句,以及需要读取表中的下一行数据的次数(而不是通过索引直接访问)。
    该值是针对单个thread的;

  查看设置:
    show variables like 'read%buffer%';
    +----------------------+----------+
    | read_buffer_size     | 2097152  |
    | read_rnd_buffer_size | 16777216 |
    +----------------------+----------+

  含义说明:
    read_buffer_size:以sequential scan方式扫描表数据时使用的buffer;调大此值能够改善全表扫描的性能;顺序读;
    read_rnd_buffer_size:以random scan方式读取数据时使用的buffer;随机读;调大该值对order by也有一定的提升;

  查看status:    
    show global status like 'com_select';
    +---------------+-----------+
    | Com_select    | 222693559 |
    +---------------+-----------+
    show global status like 'handler_read%';
    +-----------------------+-------------+
    | 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 |
    +-----------------------+-------------+

  说明:
    Com_select:服务器完成的查询请求次数:
    Handler_read_key:代表一个行被索引值读的次数,这个数越高越好;
    Handler_read_rnd_next:表示在数据文件中读下一行的请求数;这个值高,意味查询运行低效,并且应该建立索引补救;在进行大量的全表扫描时,这个值会很高;

    表扫描率 = Handler_read_rnd_next / Com_select
    如果表扫描率超过4000,说明进行了太多表扫描,很有可能索引没有建好,增加read_buffer_size值会有一些好处,但最好不要超过8MB。

*********************************************
四 innodb的设置和优化
*********************************************
  innodb采用了一些不同的机制,主要有四点:缓存机制、事务支持、锁定实现、数据存储方式

*********************************************
4.1 缓冲相关的设置

4.1.1 innodb_buffer_pool_size
  机制:
    这个参数和MyISAM的key_buffer_size有相似之处,但也是有差别的。这个参数主要缓存innodb表的索引,数据,插入数据时的缓冲。为Innodb加速优化首要参数。这个参数不能动态更改;
 
  设置建议:
    如果是一个专用DB服务器,那么他可以占到内存的70%-80%。分配过大,会使Swap占用过多,致使Mysql的查询特慢。如果你的数据比较小,那么可分配是你的数据大小+10%左右做为这个参数的值。例如:数据大小为50M,那么给这个值分配innodb_buffer_pool_size=64M

  设置的最大值限制:
    总内存 - OS系统预留 - 连接数 * (sort_buffer_size + join_buffer_size + read_buffer_size + read_rnd_buffer_size + thread_statck ) - key_cache_size

  查看status:
    show status like 'innodb_buffer_pool%';
    +---------------------------------------+-------+
    | Innodb_buffer_pool_pages_data         | 405   |
    | Innodb_buffer_pool_pages_dirty        | 0     |
    | Innodb_buffer_pool_pages_flushed      | 0     |
    | Innodb_buffer_pool_pages_free         | 2795  |
    | Innodb_buffer_pool_pages_misc         | 0     |
    | Innodb_buffer_pool_pages_total        | 3200  |
    | Innodb_buffer_pool_read_ahead         | 0     |
    | Innodb_buffer_pool_read_ahead_evicted | 0     |
    | Innodb_buffer_pool_read_requests      | 12192 |
    | Innodb_buffer_pool_reads              | 406   |
    | Innodb_buffer_pool_wait_free          | 0     |
    | Innodb_buffer_pool_write_requests     | 0     |
    +---------------------------------------+-------+

  说明:
    pages_total, pages_free可观察出pool的使用情况;
    read_requests 表示请求共12192次,reads 表示其中406次所请求的数据没有在buffer pool中;
    InnoDB Buffer命中率: innodb_buffer_read_hits = (1 - innodb_buffer_pool_reads / innodb_buffer_pool_read_requests) * 100%

  查看status方式二:
  show engine innodb status\G

  ----------------------
  BUFFER POOL AND MEMORY
  ----------------------
  Total memory allocated 4668764894; in additional pool allocated 16777216
  Dictionary memory allocated 81888
  Buffer pool size   32768
  Free buffers       32382
  Database pages     385
  Old database pages 0
  Modified db pages  0
  Pending reads 0
  Pending writes: LRU 0, flush list 0, single page 0
  Pages made young 0, not young 0
  0.00 youngs/s, 0.00 non-youngs/s
  Pages read 385, created 0, written 0
  0.00 reads/s, 0.00 creates/s, 0.00 writes/s
  No buffer pool page gets since the last printout
  Pages read ahead 0.00/s, evicted without access 0.00/s
  LRU len: 385, unzip_LRU len: 0
  I/O sum[0]:cur[0], unzip sum[0]:cur[0]

  通过其中的信息来观察pool使用情况和设置情况

4.1.2 innodb_additional_mem_pool_size
  作用:
    用来存放Innodb的字典信息和其他一些内部结构所需要的内存空间;
    这个值不用分配太大,系统可以自动调。不用设置太高。通常比较大数据设置16M够用了,如果表比较多,可以适当的增大。如果这个值自动增加,会在error log有中显示的。

4.1.3 innodb_log_buffer_size
  查看:
  show variables like 'innodb_log_buffer_size';

  机制:
    主要作用就是缓冲log数据,提高写log的io性能;
    分配原则:控制在2-8M.这个值不用太多的。他里面的内存一般一秒钟写到磁盘一次。具体写入方式和你的事务提交方式有关。在Oracle等数据库了解这个,一般最大指定为3M比较合适。

  查看status:
    show status like 'innodb_log%';
    +---------------------------+-------+
    | Innodb_log_waits          | 0     |
    | Innodb_log_write_requests | 0     |
    | Innodb_log_writes         | 1     |
    +---------------------------+-------+

  Innodb_log_waits:lob buffer的等待次数,如果这个值增长过快,可以适当的增加innodb_log_buffer_size
  另外如果你需要处理大理的test,或是blob字段,可以考虑增加这个参数的值。

4.1.4 double_write_buffer
  show variables like 'innodb_double%';
    +--------------------+-------+
    | innodb_doublewrite | ON    |
    +--------------------+-------+

  说明:
    双写是innodb为了稳定性而采用的一种保护机制,虽然会增加一点io负担,但由于是连续写消耗较小;
    在某些文件系统上不需要开启该功能;在slave上也可以禁用该机制;

4.1.5 adaptive_hash_index
  机制:
    这是innodb为了改善索引性能自动应用的一个机制,会在内部建立一个根据某个B-tree索引的hash index并根据该索引的变化自动调整,即adaptive_hash_index;
    adaptive_hash_index 仅存在于buffer pool中,本质是为了提高buffer pool中的数据访问效率,可以理解为给buffer pool中的数据做索引;

  show variables like '%adap%';
    +----------------------------+-------+
    | innodb_adaptive_flushing   | ON    |
    | innodb_adaptive_hash_index | ON    |
    +----------------------------+-------+

*********************************************
4.2 事务相关的设置

4.2.1 日志缓冲的刷新方式
  设置参数:
  innodb_flush_logs_at_trx_commit

  作用:
  控制日志缓冲中的数据刷新到磁盘文件的时机

  取值:
    0:log thread每隔1秒将log buffer中的数据写到日志文件,并且对日志文件做到磁盘操作的刷新;但事务的提交不触发以上操作。可见,mysql crash或os crash或断电后,会丢失最后一秒的事务。
    1:每次事务的结束会触发log thread将log buffer中的数据写到日志文件,并且对日志文件做到磁盘操作的刷新;这个可以做到不丢任何一个事务。
    2:每次事务的结束会触发log thread将log buffer中的数据写到日志文件,但不对日志文件做到磁盘操作的刷新;对日志文件的刷新也每秒发生一次。但需要注意的是,由于文件系统对于自己的刷新机制的不同,并不能保证每秒100%的发生。从而在性能上是最快的。但操作系统崩溃或掉电才会删除最后一秒的事务。

  建议:
    1是最安全性能最差的;0每秒一次同步性能会提高;2是性能最好的;

*********************************************
4.3 数据存储的优化

4.3.1 独立表空间的使用
  show variables like 'innodb_file_per_table';
    +-----------------------+-------+
    | innodb_file_per_table | ON    |
    +-----------------------+-------+
  设置:
  innodb_file_per_table = 1 | 0

  作用:使每个Innodb的表,有自已独立的表空间。如删除文件后可以回收那部分空间。
  分配原则:只有使用不使用。但db还需要有一个公共的表空间。

4.3.2 日志文件大小的设置
  innodb_log_file_size=256M

  分配原则:几个日值成员大小加起来差不多和你的innodb_buffer_pool_size相等。上限为每个日值上限大小为4G.一般控制在几个LOG文件相加大小在2G以内为佳。具体情况还需要看你的事务大小,数据大小为依据。
  说明:这个值分配的大小和数据库的写入速度,事务大小,异常重启后的恢复有很大的关系。小日志文件导致许多不必要的吸盘写操作。大日志文件的缺点时恢复时间更长。

4.3.3 日值组数量的设置
  innodb_log_files_in_group = 3

  分配原则:
  一般我们可以用2-3个日志组。默认为两个。

*********************************************
4.4 innodb其它方面的优化

4.4.1 innodb_flush_method
  show variables like 'innodb_flush_method';

  作用:
    设置innodb打开和同步数据文件以及日志文件的方式, 只在linux系统上可用;

  取值:
    fdatasync,默认值,通过fsync()来flush数据和日志文件数据;
    0_DSYNC,  系统以0_SYNC方式打开和刷新日志文件,通过fsync()打开和刷新数据文件;
    0_DIRECT, 通过0_DIRECT打开数据文件,同时以fsync()来刷新数据和日志文件;

  建议:
    磁盘是raid卡时,建议设为0_DIRECT;如果存储是SAN环境,使用0_DIRECT反而会降低性能;如支持0_DSYNC尽量设置此方式;

4.4.2 innodb_thread_concurrency
  作用:
  控制内部的并发处理线程数量的最大值;

  show variables like 'innodb_thread_concurrency';

  建议:
  设置为cpu个数和磁盘个数之和;

4.4.3 innodb_max_dirty_pages_pct
  作用:
    控制Innodb的脏页在缓冲中在那个百分比之下,值在范围1-100,默认为90.
    这个参数的另一个用处:当innodb的内存分配过大,致使swap占用严重时,可以适当的减小调整这个值,使达到swap空间释放出来。
    
  建议:这个值最大在90%,最小在15%。太大,缓存中每次更新需要致换数据页太多,太小,放的数据页太小,更新操作太慢。

4.4.4 innodb_open_files
  show variables like '%innodb_open_files%';

  作用:限制Innodb能打开的表的数据。
  分配原则:如果库里的表特别多的情况,请增加这个。这个值默认是300,并适当的增加table_cache

4.4.5 innodb_file_io_threads, innodb_write_io_threads
  作用:文件读写io数

  show variables like 'innodb%threads%';
    +-------------------------+-------+
    | innodb_purge_threads    | 0     |
    | innodb_read_io_threads  | 8     |
    | innodb_write_io_threads | 8     |
    +-------------------------+-------+

  这个参数只在Windows上起作用。在LINUX上只会等于4

*********************************************
五 MyISAM的设置和优化
*********************************************
5.1 Key_buffer_size

    key_buffer_size,(全局变量) (只针对MyISAM表) 空置分配给MyISAM索引缓存的内存总数,是对MyISAM表性能影响最大的一个参数。理想情况下,对于这些块的请求应该来自于内存,而不是来自于磁盘。

    下面一台以MyISAM为主要存储引擎服务器的配置,分配了解了512M:

    mysql> show variables like 'key_buffer_size';
    +-----------------+------------+
    | Variable_name   | Value      |
    +-----------------+------------+
    | key_buffer_size | 536870912  |
    +-----------------+------------+

    我们再看一下key_buffer_size的使用情况:

    mysql> show global status like 'key_read%';
    +------------------------+-------------+
    | Variable_name          | Value       |
    +------------------------+-------------+
    | Key_read_requests      | 27813678764 |
    | Key_reads              | 6798830     |
    +------------------------+-------------+

    Key_reads 代表命中磁盘的请求个数,Key_read_requests 是总数。命中磁盘的读请求数除以读请求总数就是不中比率。

    索引未命中缓存的概率(key_cache_miss_rate)= Key_reads / Key_read_requests * 100%

    key_cache_miss_rate在0.1%以下都很好(每1000个请求有一个直接读硬盘),如果key_cache_miss_rate在 0.01%以下的话,key_buffer_size分配的过多,可以适当减少。

    一共有27813678764个索引读取请求,有6798830个请求在内存中没有找到直接从硬盘读取索引,key_cache_miss_rate为0.0244%,4000个索引读取请求才有一个直接读硬盘,已经很BT 了。  
    

    MySQL服务器还提供了key_blocks_*参数:

    mysql> show global status like 'key_blocks_u%';
    +------------------------+-------------+
    | Variable_name          | Value       |
    +------------------------+-------------+
    | Key_blocks_unused      | 0           |
    | Key_blocks_used        | 413543      |
    +------------------------+-------------+

    Key_blocks_unused表示未使用的缓存簇(blocks)数,Key_blocks_used表示曾经用到的最大的blocks数,比如这台服务器,所有的缓存都用到了,要么增加key_buffer_size,要么就是过渡索引了,把缓存占满了。比较理想的设置:

    Key_blocks_used / (Key_blocks_unused + Key_blocks_used) * 100% ≈ 80%

*********************************************
六 其他的设置
*********************************************
6.1 禁用文件系统外部锁
  skip_external_locking=1

  或
  external-locking=0
 
 
*********************************************
七 常用的监控
*********************************************
7.1 监控QPS(每秒Query量)
  show status like 'Question';

  QPS = Questions(or Queries) / seconds

7.2 监控TPS(每秒事务量)

   show status like 'Com_commit';
   show status like 'Com_rollback';

   TPS = (Com_commit + Com_rollback) / seconds

7.3 key buffer命中率
  key_buffer_read_hits = (1-key_reads/key_read_requests)*100%
  key_buffer_write_hits = (1-key_writes/key_write_requests)*100%

  show status like 'key%';

7.4 innodb buffer命中率
  innodb_buffer_read_hits = (1-innodb_buffer_pool_reads/innodb_buffer_pool_read_requests)*100%;
  innodb_buffer_pool_reads 表示未在cache的请求数

  show status like 'innodb_buffer_pool_read%';

7.5 query cache命中率
  query_cache_hits = (qcache_hits/(qchcae_hits+qcache_inserts))*100%;

  show status like 'qcache%';

7.6 table cache状态量
  大体可用此计算(虽然并不准确):open_tables/opend_tables

  show status like 'open%tables%';

7.7 thread cache命中率
  thread_cache_hits = (1-threads_created/connections)*100%;

  show status where variable_name like 'threads_created' or variable_name like 'connections';
  要达到90%以上;

7.8 table_locks
  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就足够了。

7.9 innodb行锁争用情况
  show status like 'innodb_row_lock%';
  +-------------------------------+-------+
  | Innodb_row_lock_current_waits | 0     |
  | Innodb_row_lock_time          | 0     |
  | Innodb_row_lock_time_avg      | 0     |
  | Innodb_row_lock_time_max      | 0     |
  | Innodb_row_lock_waits         | 0     |
  +-------------------------------+-------+

  如果innodb_row_lock_waits和innodb_row_lock_time_avg的值较高,则行锁争用情况比较严重;
  可通过设置innodb monitors来进一步观察发生锁冲突的表和数据行等;

7.10 replication延时量
  show slave status\G

  seconds_behind_master的值反映slave延时量;

7.11 tmp table情况
  show status like 'created_tmp%';
    +-------------------------+-------+
    | Created_tmp_disk_tables | 0     |
    | Created_tmp_files       | 5     |
    | Created_tmp_tables      | 19    |
    +-------------------------+-------+

  理想情况:Created_tmp_disk_tables / Created_tmp_tables * 100% <= 25%
 
7.12 binlog cache使用情况
  show status like 'binlog_cache%';
    +-----------------------+-------+
    | Binlog_cache_disk_use | 0     |
    | Binlog_cache_use      | 0     |
    +-----------------------+-------+
  Binlog_cache_disk_use 不为0说明binlog_cache_size不够;

7.13 innodb_log_waits量
  show status like 'innodb_log%';
    +---------------------------+-------+
    | Innodb_log_waits          | 0     |
    | Innodb_log_write_requests | 0     |
    | Innodb_log_writes         | 1     |
    +---------------------------+-------+
  Innodb_log_waits 不为0或随着时间增长,则说明innodb_log_buffer_size不够;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值