• MySQL-配置优化技巧


    一、连接请求配置

    1.查询当前连接数(show full processlist)

    show full processlist;

    2.最大连接数(max_connections)

      max_connections, 增加该值增加 mysqld 要求的文件描述符的数量, 如果服务器的并发连接请求量比较大, 建议调高此值, 以增加并行连接数量, 当然这建立在机器能支撑的情况下, 因为如果连接数越多, 介于MySQL会为每个连接提供连接缓冲区, 就会开销越多的内存, 所以要适当调整该值, 不能盲目提高设值, 一个连接占用多少内存取决于执行什么操作(比如查询出的数据量大理所当然费内存), 每个连接到MySQL服务器的线程都需要有自己的缓冲, 大概需要立刻分配256K

      1).查询最大连接数

    show variables like 'max_connections';

      2).查询一下MySQL服务器过去的最大连接数(服务器响应的最大连接数)

    show global status like 'max_used_connections';

      3).根据MySQL服务器过去的最大连接数(max_used_connections)设置最大连接数(max_connections), 对于MySQL服务器最大连接数值的设置范围比较理想的是:服务器响应的最大连接数值占服务器上限连接数值的比例值在10%以上, 如果在10%以下, 说明MySQL服务器最大连接上限值设置过高, max_used_connections / max_connections * 100% (理想值≈ 85%)

    set global max_connections=XXX;--XXX为设置的数值

      4).注意不能设置过多max_connections, 在32位GNU/Linux x86上, 如果下列表达式的值接近或者超过2GB,系统会面临危机

      innodb_buffer_pool_size + key_buffer_size + max_connections * (sort_buffer_size + read_buffer_size + binlog_cache_size) + max_connections * 2MB每个线程使用一个堆栈(通常是2MB, 但在MySQL AB二进制分发版里只有256KB)并且在最坏的情况下也使用sort_buffer_size + read_buffer_size附加内存

    3.每个用户的最大连接数(max_user_connections)

    4.MySQL能暂存的连接数量(back_log)

      当主要MySQL线程在一个很短时间内得到非常多的连接请求, 这就起作用, 如果MySQL的连接数据达到max_connections时, 新来的请求将会被存在堆栈中, 以等待某一连接释放资源, 该堆栈的数量即back_log, 如果等待连接的数量超过back_log, 将不被授予连接资源

      back_log值指出在MySQL暂时停止回答新请求之前的短时间内有多少个请求可以被存在堆栈中, 只有如果期望在一个短时间内有很多连接, 你需要增加它, 换句话说, 这值对到来的TCP/IP连接的侦听队列的大小

      当观察你主机进程列表(show full processlist), 发现大量264084 | unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时, 就要加大back_log的值了

      back_log值不能超过TCP/IP连接的侦听队列的大小, 若超过则无效, 查看当前系统的TCP/IP连接的侦听队列的大小命令:

    cat /proc/sys/net/ipv4/tcp_max_syn_backlog #目前系统为1024, 对于Linux系统推荐设置为小于512的整数

      默认数值是50, 可调优为128, 对于Linux系统设置范围为小于512的整数

      1).查询当前能暂存的连接数量

    show variables like 'back_log';

    二、缓冲区变量配置

      数据库属于IO密集型的应用程序, 其主职责就是数据的管理及存储工作, 而我们知道, 从内存中读取一个数据库的时间是微秒级别, 而从一块普通硬盘上读取一个 IO是在毫秒级别, 二者相差3个数量级, 所以, 要优化数据库, 首先第一步需要优化的就是IO, 尽可能将磁盘IO转化为内存IO, 本文先从MySQL数据库 IO相关参数(缓存参数)的角度来看看可以通过哪些参数进行IO优化

    全局缓冲

      启动MySQL时就要分配并且总是存在的全局缓存, 目前有:key_buffer_size(默认值:402653184, 即384M)、innodb_buffer_pool_size(默认值:134217728即:128M)、innodb_additional_mem_pool_size(默认值:8388608即:8M)、innodb_log_buffer_size(默认值:8388608即:8M)、query_cache_size(默认值:33554432即:32M)等五个, 总共:560M

    1.索引缓冲区大小(key_buffer_size)

      key_buffer_size指定索引缓冲区的大小, 它决定索引处理的速度, 尤其是索引读的速度, 增加它可得到更好处理的索引(对所有读和多重写), 对MyISAM表性能影响最大的一个参数, 但是如果你使它太大, 系统将开始换页并且真的变慢了, 严格说是它决定了数据库索引处理的速度, 尤其是索引读的速度. 通过检查状态值 key_read_requests 和 key_reads, 可以知道 key_buffer_size 设置是否合理, 比例 key_reads / key_read_requests 应该尽可能的低, 至少是1:100, 1:1000更好(上述状态值可以使用SHOW STATUS LIKE ‘key_read%’获得)

      key_buffer_size只对MyISAM表起作用, 即使你不使用MyISAM表, 但是内部的临时磁盘表是MyISAM表, 也要使用该值, 可以使用检查状态值created_tmp_disk_tables得知详情

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

      key_buffer_size为512MB

    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 * 100%, 设置在1/1000左右较好

      默认配置数值是8388600(8M), 主机有4GB内存, 可以调优值为268435456(256MB)

    2.查询缓冲区大小(query_cache_size)

      使用查询缓冲, MySQL将查询结果存放在缓冲区中, 今后对于同样的SELECT语句(区分大小写), 将直接从缓冲区中读取结果(两次读取SQL语句必须完全一致)

      1).查询查询缓冲区设置情况

    mysql> show variables like 'query_cache%';
    
    +————————————–+————–+
    
    | Variable_name            | Value      |
    
    +————————————–+———–+
    
    | query_cache_limit         | 2097152     |
    
    | query_cache_min_res_unit      | 4096    |
    
    | query_cache_size         | 203423744 |
    
    | query_cache_type        | ON           |
    
    | query_cache_wlock_invalidate | OFF   |
    
    +————————————–+—————+

      query_cache_type指定是否使用查询缓冲, 可以设置为0、1、2, 该变量是SESSION级的变量

      query_cache_limit指定单个查询能够使用的缓冲区大小, 缺省为1M

      query_cache_min_res_unit指定分配缓冲区空间的最小单位, 缺省为4K(检查状态值qcache_free_blocks, 如果该值非常大, 则表明缓冲区中碎片很多, 这就表明查询结果都比较小, 此时需要减小query_cache_min_res_unit)

      2).查询查询缓冲区命中等情况

    mysql> show global status like 'qcache%';
    
    +——————————-+—————–+
    
    | Variable_name                  | Value        |
    
    +——————————-+—————–+
    
    | 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 / 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_inserts) / Qcache_hits * 100%

      示例服务器查询缓存碎片率 = 20.46%, 查询缓存利用率 = 62.26%, 查询缓存命中率=1.94%, 命中率很差, 可能写操作比较频繁吧, 而且可能有些碎片

    每个连接的缓冲

      3.每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区大小(record_buffer_size)

      如果你做很多顺序扫描, 你可能想要增加该值, 默认数值是131072(128K), 可改为16773120 (16M)

      4.随机读缓冲区大小(read_rnd_buffer_size)

      当按任意顺序读取行时(例如,按照排序顺序), 将分配一个随机读缓存区, 进行排序查询时, MySQL会首先扫描一遍该缓冲, 以避免磁盘搜索, 提高查询速度, 如果需要排序大量数据, 可适当调高该值, 但MySQL会为每个客户连接发放该缓冲空间, 所以应尽量适当设置该值, 以避免内存开销过大, 一般可设置为16M

      5.排序缓冲区大小(sort_buffer_size)

      每个需要进行排序的线程分配该大小的一个缓冲区, 增加这值加速ORDER BY或GROUP BY操作, 默认数值是2097144(2M), 可改为16777208 (16M)

      6.联合查询操作所能使用的缓冲区大小(join_buffer_size)

      record_buffer_size, read_rnd_buffer_size, sort_buffer_size, join_buffer_size为每个线程独占, 也就是说, 如果有100个线程连接, 则占用为16M * 100

      7.表缓冲区大小(table_cache)

      每当MySQL访问一个表时, 如果在表缓冲区中还有空间, 该表就被打开并放入其中, 这样可以更快地访问表内容, 通过检查峰值时间的状态值Open_tables和Opened_tables, 可以决定是否需要增加table_cache的值, 如果你发现open_tables等于table_cache, 并且opened_tables在不断增长, 那么你就需要增加table_cache的值了(上述状态值可以使用SHOW STATUS LIKE 'Open%tables'获得), 注意, 不能盲目地把table_cache设置成很大的值, 如果设置得太高, 可能会造成文件描述符不足, 从而造成性能不稳定或者连接失败

      1G内存机器, 推荐值是128-256, 内存在4GB左右的服务器该参数可设置为256M或384M

      8.用户可以创建的内存表(memory table)的大小(max_heap_table_size)

      这个值用来计算内存表的最大行数值, 这个变量支持动态改变, 即set @max_heap_table_size=#  这个变量和tmp_table_size一起限制了内部内存表的大小, 如果某个内部heap(堆积)表大小超过tmp_table_size, MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表

      9.临时表大小(tmp_table_size)

      通过设置tmp_table_size选项来增加一张临时表的大小, 例如做高级GROUP BY操作生成的临时表, 如果调高该值, MySQL同时将增加heap表的大小, 可达到提高联接查询速度的效果, 建议尽量优化查询, 要确保查询过程中生成的临时表在内存中, 避免临时表过大导致生成基于硬盘的MyISAM表

    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增加, 如果临时表大小超过tmp_table_size, 则是在磁盘上创建临时表, 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%, 应该相当好了

      默认为16M, 可调到64-256最佳, 线程独占, 太大可能内存不够I/O堵塞

      10.可以复用的保存在中的线程的数量(thread_cache_size)

      可以复用的保存在中的线程的数量, 如果有, 新的线程从缓存中取得, 当断开连接的时候如果有空间, 客户的线置在缓存中, 如果有很多新的线程, 为了提高性能可以这个变量值

      通过比较Connections和Threads_created状态的变量, 可以看到这个变量的作用

      默认值为110, 可调优为80

      11.thread_concurrency

      推荐设置为服务器 CPU核数的2倍, 例如双核的CPU, 那么thread_concurrency的应该为4, 2个双核的cpu, thread_concurrency的值应为8, 默认为8

      12.服务器关闭非交互连接(闲置连接)之前等待活动的秒数(wait_timeout, 单位为秒), 服务器关闭交互式连接(非闲置连接)前等待活动的秒数(interactive_timeout)

      MySQL客户端的数据库连接闲置最大时间值,  说得比较通俗一点, 就是当你的MySQL连接闲置超过一定时间后将会被强行关闭

      MySQL默认的wait-timeout  值为8个小时, 可以通过命令show variables like 'wait_timeout'查看结果值; 设置这个值是非常有意义的, 比如你的网站有大量的MySQL链接请求(每个MySQL连接都是要内存资源开销的 ), 由于你的程序的原因有大量的连接请求空闲啥事也不干, 白白占用内存资源, 或者导致MySQL超过最大连接数从来无法新建连接导致“Too many connections”的错误, 在设置之前你可以查看一下你的MYSQL的状态(可用show processlist), 如果经常发现MYSQL中有大量的Sleep进程, 则需要 修改wait-timeout值了

      交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端

      在线程启动时, 根据全局wait_timeout值或全局 interactive_timeout值初始化会话wait_timeout值, 取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义), 这两个参数必须配合使用, 否则单独设置wait_timeout无效

      对于4GB左右内存的服务器可以设置为5-10

    配置InnoDB的几个变量

      1.缓冲数据和索引(innodb_pool_buffer_size)

      对于InnoDB表来说, innodb_buffer_pool_size的作用就相当于key_buffer_size对于MyISAM表的作用一样, InnoDB使用该参数指定大小的内存来缓冲数据和索引, 对于单独的MySQL数据库服务器, 最大可以把该值设置成物理内存的80%

      除innodb_buffer_pool_size用于存储页面缓存数据外,另外正常情况下还有大约8%的开销,主要用在每个缓存页帧的描述、adaptive hash等数据结构,如果不是安全关闭,启动时还要恢复的话,还要另开大约12%的内存用于恢复,两者相加就有差不多21%的开销。假设:12G的innodb_buffer_pool_size,最多的时候InnoDB就可能占用到14.5G的内存。若系统只有16G,而且只运行MySQL,且MySQL只用InnoDB,那么为MySQL开12G,是最大限度地利用内存了

      另外InnoDB和 MyISAM 存储引擎不同, MyISAM 的 key_buffer_size 只能缓存索引键,而 innodb_buffer_pool_size 却可以缓存数据块和索引键。适当的增加这个参数的大小,可以有效的减少 InnoDB 类型的表的磁盘 I/O

      通过 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 计算缓存命中率,并根据命中率来调整 innodb_buffer_pool_size 参数大小进行优化

    show status like 'Innodb_buffer_pool_read%'

      根据MySQL手册, 对于2G内存的机器, 推荐值是1G(50%)

      2.innodb将log buffer中的数据写入日志文件并flush磁盘的时间点(innodb_flush_log_at_trx_commit)

      主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点, 取值分别为0、1、2三个; 0, 表示当事务提交时, 不做日志写入操作, 而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次; 1, 则在每秒钟或是每次事物的提交都会引起日志文件写入、flush磁盘的操作, 确保了事务的ACID; 设置为2, 每次事务提交引起写入日志文件的动作, 但每秒钟完成一次flush磁盘操作

      实际测试发现, 该值对插入数据的速度影响非常大, 设置为2时插入10000条记录只需要2秒, 设置为0时只需要1秒, 而设置为1时则需要229秒, 因此, MySQL手册也建议尽量将插入操作合并成一个事务, 这样可以大幅提高速度

      根据MySQL手册, 在允许丢失最近部分事务的危险的前提下, 可以把该值设为0或2

      3.LOG缓冲区大小(innodb_log_buffer_size)

      log缓存大小, 一般为1-8M, 默认为1M, 对于较大的事务, 可以增大缓存大小

      可设置为4M或8M

      4.用来存储数据字典和其他内部数据结构的内存池大小(innodb_additional_mem_pool_size)

      该参数指定InnoDB用来存储数据字典和其他内部数据结构的内存池大小, 缺省值是1M, 通常不用太大, 只要够用就行, 应该与表结构的复杂度有关系, 如果不够用, MySQL会在错误日志中写入一条警告信息

      根据MySQL手册, 对于2G内存的机器, 推荐值是20M, 可适当增加

      5.innodb_thread_concurrency

      推荐设置为 2*(NumCPUs+NumDisks), 默认一般为8

    三、其他配置

      1.禁止MySQL对外部连接进行DNS解析(skip-name-resolve)

        使用这一选项可以消除MySQL进行DNS解析的时间, 但需要注意, 如果开启该选项, 则所有远程主机连接授权都要使用IP地址方式, 否则MySQL将无法正常处理连接请求

      2.查看表信息

    SHOW TABLE STATUS LIKE '表名'

      3.

    四、一些配置推荐

    #InnoDB存储数据字典、内部数据结构的缓冲池,16MB 已经足够大了。
    innodb_additional_mem_pool_size = 16M
    
    #InnoDB用于缓存数据、索引、锁、插入缓冲、数据字典等
    #如果是专用的DB服务器,且以InnoDB引擎为主的场景,通常可设置物理内存的50%
    #如果是非专用DB服务器,可以先尝试设置成内存的1/4,如果有问题再调整
    #默认值是8M,非常坑X,这也是导致很多人觉得InnoDB不如MyISAM好用的缘故
    innodb_buffer_pool_size = 4G
    
    #InnoDB共享表空间初始化大小,默认是 10MB,也非常坑X,改成 1GB,并且自动扩展
    innodb_data_file_path = ibdata1:1G:autoextend
    
    #如果不了解本选项,建议设置为1,能较好保护数据可靠性,对性能有一定影响,但可控
    innodb_flush_log_at_trx_commit = 1
    
    #InnoDB的log buffer,通常设置为 64MB 就足够了
    innodb_log_buffer_size = 64M
    
    #InnoDB redo log大小,通常设置256MB 就足够了
    innodb_log_file_size = 256M
    
    #InnoDB redo log文件组,通常设置为 2 就足够了
    innodb_log_files_in_group = 2
    
    #启用InnoDB的独立表空间模式,便于管理
    innodb_file_per_table = 1
    
    #启用InnoDB的status file,便于管理员查看以及监控等
    innodb_status_file = 1
    
    #设置事务隔离级别为 READ-COMMITED,提高事务效率,通常都满足事务一致性要求
    transaction_isolation = READ-COMMITTED 
    

       在这里,其他配置选项也需要注意:

    #设置最大并发连接数,如果前端程序是PHP,可适当加大,但不可过大
    #如果前端程序采用连接池,可适当调小,避免连接数过大
    max_connections = 60
    
    #最大连接错误次数,可适当加大,防止频繁连接错误后,前端host被mysql拒绝掉
    max_connect_errors = 100000
    
    #设置慢查询阀值,建议设置最小的 1 秒
    long_query_time = 1
    
    #设置临时表最大值,这是每次连接都会分配,不宜设置过大 max_heap_table_size 和 tmp_table_size 要设置一样大
    max_heap_table_size = 96M
    tmp_table_size = 96M
    
    #每个连接都会分配的一些排序、连接等缓冲,一般设置为 2MB 就足够了
    sort_buffer_size = 2M
    join_buffer_size = 2M
    read_buffer_size = 2M
    read_rnd_buffer_size = 2M
    
    #建议关闭query cache,有些时候对性能反而是一种损害
    query_cache_size = 0
    
    #如果是以InnoDB引擎为主的DB,专用于MyISAM引擎的 key_buffer_size 可以设置较小,8MB 已足够
    #如果是以MyISAM引擎为主,可设置较大,但不能超过4G
    #在这里,强烈建议不使用MyISAM引擎,默认都是用InnoDB引擎
    key_buffer_size = 8M
    
    #设置连接超时阀值,如果前端程序采用短连接,建议缩短这2个值
    #如果前端程序采用长连接,可直接注释掉这两个选项,是用默认配置(8小时)
    interactive_timeout = 120
    wait_timeout = 120
    
    a) 所有InnoDB数据表都创建一个和业务无关的自增数字型作为主键,对保证性能很有帮助;
    b) 杜绝使用text/blob,确实需要使用的,尽可能拆分出去成一个独立的表;
    c) 时间戳建议使用 TIMESTAMP 类型存储;
    d) IPV4 地址建议用 INT UNSIGNED 类型存储;
    e) 性别等非是即非的逻辑,建议采用 TINYINT 存储,而不是 CHAR(1);
    f) 存储较长文本内容时,建议采用JSON/BSON格式存储;

    qchache是缓存的是sql的结果集,最简单的情况是sql一直不重复,那qcache的命令率肯定是0
    buffer pool缓存在内存数据,sql再变 只要数据都在内存,那么命中率就是100%

     

    参考:

    MySQL性能优化之参数配置 http://blog.csdn.net/nightelve/article/details/17393631

    一步到位之InnoDB http://ourmysql.com/archives/1164?f=wb

  • 相关阅读:
    理解和解决MySQL乱码问题
    搞清字符集和字符编码
    linux下卸载mysql
    mysqldump备份
    mysql 数据类型
    微信对接HIS——微信可查检验结果
    Install Haskell on Ubuntu and CentOS
    php用类生成二维码
    UVA Team Queue
    总有一种正能量触动你的心灵,读刘丁宁的一封信
  • 原文地址:https://www.cnblogs.com/JohnABC/p/4382214.html
Copyright © 2020-2023  润新知