mysql优化服务器设置 高性能mysql笔记

MySQL有大量可以修改的参数,不应该随便修改。通常只需把基本参数配置正确(大部分情况下只需配置很少一部分参数),应该将更多的时间花在schema的优化、索引,以及查询设计上。在正确地配置了MySQL的基本配置项之后,再花力气去修改其它配置项的收益通常就比较小了。

mysql 配置文件位置

  • mysql 的配置文件一般默认在/etc/my.cnf 或者/etc/mysql/my.cnf 。
  • 如果不知道当前使用的配置文件的路径,可以尝试下面的操作:
# which mysqld
/usr/local/mysql/bin/mysqld
# /usr/local/mysql/bin/mysqld --verbose --help |grep -A 1 'Default options'
2016-06-02 16:49:39 0 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.6.25-log) starting as process 8253 ...
2016-06-02 16:49:41 8253 [Note] Plugin 'FEDERATED' is disabled.
Default options are read from the following files in the given order: 默认的选项是按照给定的顺序读取从以下文件:
/etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf 

mysql 配置的工作原理

  1. 语法、作用域、动态性

    • 语法:配置项设置使用小写,单词间下划线或横线,固定格式

    • 作用域:服务器级别(全局作用域)、每个连接(会话)、对象级

      改变会话级变量只影响当前连接

      query_cache_size:全局。
      sort_buffer_size:全局、每个线程可设。
      join_buffer_size:全局默认,且线程可设,若一查询关联多张表,可为每个关联分配一个关联缓冲。
      show global variables:查看全局设置是否生效。
      show session variables:查看会话级别的变量。
      show session variables like ‘auto%’(变量名):查看会话级指定变量。
      show global variables like ‘auto%’(变量名):查看全局级指定变量;
      set autocommit(变量名) =‘off’(修改的某个值);
      set @@session.变量名 =‘off’(修改的某个值);
      set global autocommit(变量名) =‘off’(修改的某个值);

  2. 设置变量的副作用

    注意:有些配置动态修改可能导致mysql做大量工作。

    1. key_bufer_size:一次性为键缓存区分配all指定的空间,如果把非默认键缓冲设置为0,mysql会使用默认键缓冲,如果设置非0,mysql会刷新键缓冲内容这回导致阻塞其他线程不能访问直到刷新完成。
    2. table_cache_size:延迟到下次有线程打开表,检查该量,大于缓存中表数量、把最新打开的表放入缓存,小于删除不常用表。
    3. thread_cache_size:用来缓存空闲的线程,线程关闭时检查改量如果有内存则缓存线程如果没有则删除。
    4. query_cache_size:查询缓存保存查询返回的完整结果,启动时一次性分配初始化该内存,修改后会立刻 ‘逐个清除’ 查询的缓存 然后重新分配内存,完成之前服务器无法提供服务。
    5. read_buffer_size:从磁盘读取数据时分配的缓存大小,有查询需要使用才为该缓存分片内存,一次性分指定大小
    6. read_rnd_buffer_size:MySQL 的随机读缓冲区大小。当按任意顺序读取行时(例如按照排序顺序),将分配一个随机读缓存区。 进行排序查询时,MySQL 会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。 但 MySQL 会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
    7. sort_buffer_size:MySQL 执行排序使用的缓冲大小,查询需要做排序才为缓存分配指定大小。

配置内存使用

按照以下步骤配置内存:

  1. 确定可以使用内存上限。
  2. 确定每个连接mysql需要使用多少内存,例如排序缓冲和临时表。
  3. 确定操作系统和其他程序需要多少内存。
  4. 把剩下的内存全部给mysql的缓存。

重要的缓存:

  1. innoDB缓冲池。
  2. innoDB日志文件和MyISAM的操作系统缓存。
  3. MyISAM键缓存。
  4. 查询缓存
  5. 无法手工配置的缓存例如二进制日志文件的表定义文件的操作系统缓存。

InnoDB缓冲池

InnoDB缓冲池特别需要内存。

  1. InnoDB缓冲池保存索引,行数据,自适应哈希索引,插入缓冲区,锁及其它内部结构。InnoDB也使用了缓冲池帮助延迟写入,它可以合并更多写入然后顺序的执行。总之严重依赖缓冲池。
  2. MySQL手册建议在专用服务器上80%的物理内存分配给缓冲池。实际上如果机器内存很大的话,还能分配更多
  3. 缓冲池很大也会导致启动和关闭变慢,启动:由于启动要让服务器热起来要把很多东西放到缓存所以如果磁盘慢启动会很慢,关闭:由于关闭要把脏页刷新到磁盘如果内存过大会有大量脏页所以会很慢关闭前可以通过innodb_max_dirty_pages_pct的值,让InnoDB改变保留在缓冲池中被修改的页面的数量。

有一个流行的经验法则说,应该把缓冲池大小设置为服务器内存的约75~80%,但并不总是正确的。有一个更好的办法来设置缓冲池大小,大致如下:

  1. 从服务器内存总量开始

  2. 减去操作系统的内存占用

  3. 减去一些MySQL自身需要的内存

  4. 减去足够让操作系统缓存InnoDB日志文件的内存,至少是足够缓存最近经常访问的部分。

  5. 减去其他配置的MySQL缓冲和缓存需要的内存,例如查询缓存,MYISAM键缓存

MyISAM键缓存

  MyISAM只缓存索引不缓存数据 可以设置多个键缓存最重要的是 key_buffer_size.

  1. 获取缓存索引空间大小:select sum(index_length) from information_schema.tables where engine=‘myisam’
  2. 键缓存大小设置为不要超过索引总和大小和为操作系统保留的缓存的25%-50%。
  3. 键缓存可设置多个:设置多个在配置文件中添加
    key_buffer_1.key_buffer_size=1G
    key_buffer_2.key_buffer_size=2G
    把table1和2 的索引放到key_buffer_2中
    cache index table1,table2 in key_buffer_2
  4. 缓存命中率: 100 - ( (Key_reads * 100) / Key_read_requests )
  5. 缓存使用百分比:100 - ( (Key_blocks_unused * key_cache_block_size) * 100 / key_buffer_size)
  6. 即使没有使用MyISAM表,也要给key_buffer_size设置少量的内存,比如32MB。MySQL有时会使用MyISAM执行一些内部操作,比如给有GROUP BY的查询提供临时表。
  7. MyISAM数据块大小:myisam_block_size =1024 设置数据块大小1kb。
      写时读取:
      x86 处理器一般操作系统页为4kb如果MyISAM是1kb 与操作系统不一样会发生写时读取 比如 在步骤四发生写时读取。
    1. MyISAM 从磁盘读取1kb的块
    2. 操作系统读取4kb 发送给MyISAM 1kb 然后丢弃其他的
    3. MyISAM 修改完1kb发给操作系统写入磁盘
    4. 操作系统从磁盘读取4kb然后修改MyISAM修改过的一部分再写入磁盘(此时发生了写时读取 所以如果把MyISAM的块设置为4kb就不会发生写时读写)

线程缓存

  线程缓存保存休眠状态的线程。当一个新的连接创建时,如果缓存中有线程存在,MySQL从缓存中删除一个线程,并且把它分配给这个新的连接。当连接关闭时,如果线程缓存还有空间的话,MySQL又会把线程放回缓存。如果没有空间的话,MySQL会销毁这个线程。只要MySQL在缓存里还有空闲的线程,它就可以迅速地响应连接请求,因为这样就不用为每个连接创建新的线程。
  设置线程池:
1.thread_cache_size:设置缓存线程数(一般不用配置,除非有很多连接请求)。
  可以通过观察Threads_connected变量来设置thread_cache_size,每个休眠状态的线程,通常大小256KB内存。相对于正在处理查询的线程来说,这个内存不算很大。

  • 每秒:Threads_connected100-200 thread_cache_size 可以设置20
  • 每秒:Threads_connected500-700 thread_cache_size 可以设置200

表缓存

  表缓存存储了能 表示 表的对象。缓存中每个对象都包含了解析表后生成的.frm文件和其他数据,对象中的其他东西依赖于标的存储引擎。

  1. 表缓存有助于复用资源。
    对于MyISAM来说表缓存可以避免重复修改文件头
    表缓存的设计有点以MyISAM为中心,对于InnoDB来说,表缓存没那么重要,InnoDB在很多方面都不会依赖于它(例如保存文件描述符,InnoDB为此有自己的表缓存)。但是,InnoDB还是可以从解析后的.frm文件中获益。

  2. 表缓存被分成两个部分:一部分为打开表。另一部分为表的定义(通过table_open_cache和talbe_definition_cache定义)…通常可以吧table_definition_cache的值设置的足够高,以缓存所有表的定义。

  3. opened_tables的值很大或者正在上升,就说明表缓存不够大,应该增加系统变量table_cache的值(在MySQL中时table_open_cache)。

注意:

  • 如果MySQL不能打开更多文件的错误提示,更改open_files_limit解决这个问题。
  • 线程和表缓存其实都不会使用太多内存,他们的好处在于可以保存资源。在高并发条件下,提供高效率。

InnoDB 数据字典

  1. InnoDB自己有对每个表的缓存,叫做"表定义缓存"或者"数据字典",它是不可配置的。

  2. 当InnoDB打开一个表的时候,它就向字典中添加一个相应的对象。表关闭时,他不会被从字典中删除。

  3. 如果用innode_file_per_table选项,那么对InnoDB任何时候能打开的.ibd文件数量还有另一个限制。这是由InnoDB存储引擎处理的,不是MySQL服务器,它受innodb_open_files的控制。

  4. InnoDB为每个.idb文件使用全局文件描述符。给innodb_open_files设置足够大,这样服务器就可以保留所有同时打开的.ibd文件。

配置InnoDB的i/o行为

  InnoDB使用日志来减少提交事务时的开销。因为日志中已经记录了事务,就无须在每个事务提交时把缓冲池的脏块刷新(flush)到磁盘中。事务修改的数据和索引通常会映射到表空间的随机位置,所以刷新这些变更到磁盘需要很多随机IO。InnoDB假设使用常规磁盘,随机IO比顺序IO昂贵得多,因为一个IO请求需要时间把磁头移到正确的位置,然后等待磁盘上读出需要的部分,再转到开始位置。

  1. InnoDB用日志把随机IO变成顺序IO。一旦日志安全写到磁盘,事务就持久化了,即使断电了,InnoDB可以重放日志并且恢复已经提交的事务。

  2. InnoDB使用一个后台线程智能地刷新这些变更到数据文件。这个线程可以批量组合写入,使得数据写入更顺序,以提高效率。

  3. 日志文件大小设置 innodb_log_file_size和innodb_log_files_in_group两个参数,这对写性能非常重要。日志文件的总大小是每个文件的大小之和。

  4. InnoDB使用多个文件作为一组循环日志。通常不需要修改默认的日志数量,只修改每个日志文件的大小即可。要修改日志文件大小,需要完全关闭MySQL,将旧的日志文件移到其他地方保存,重新配置参数。

  5. 要确定理想的日志文件大小,必须权衡正常数据变更的开销和崩溃恢复需要的时间,如果日志太小,InnoDB必然将做更多的检查点,导致更多的日志写。如果日志太大,在崩溃恢复时InnoDB可能不得不做大量的工作。

  6. 当InnoDB变更任何数据时,会写一条变更记录到内存日志缓冲区中。在缓冲满的时候,事务提交的时候,或者每一秒钟,这三个条件无论哪个先达到,InnoDB都会刷新缓冲区的内容到磁盘日志文件。变量innodb_log_buffer_size可以控制日志缓冲区的大小,默认为1M。通常不需要把日志缓冲区设置得非常大。推荐的范围是1~8M。作为一个经验法则,日志文件的全部大小,应该足够容纳服务器一个小时的活动内容。

  7. InnoDB怎么刷新日志缓冲?当InnoDB把日志缓冲刷新到磁盘日志文件时,会先使用一个Mutex锁住缓冲区,刷新到所需要的位置,然后移动剩下的条目到缓冲区的前面。日志缓冲必须被刷新到持久化存储,以确保提交的事务完全被持久化了。如果和持久相比更在乎性能,可以修改innodb_flush_log_at_trx_commit变量来控制日志缓冲刷新的频繁程度。可能的设置如下:

  • 0:每秒一次把日志缓冲写到日志文件,但是事务提交时不做任何时。

  • 1:将日志缓冲写到日志文件,然后每次事务提交都刷新到持久化存储(默认并且最安全的设置),该设置保证不会丢失任何已提交的事务。

  • 2:每秒钟做一次刷新,但每次提交时把日志缓冲写到日志文件,但是不刷新到持久化存储。

  “把日志缓冲写到日志文件”和“把日志刷新到持久化存储”是不同的。在大部分操作系统中,把缓冲写到日志只是简单地把数据从InnoDB的内存缓冲转移到了操作系统的缓存,也是在内存里,并没有真正把数据写到持久化存储。

  如果MySQL崩溃了或者断电了,设置0和2通常会导致最多1秒的数据丢失,因为数据可能存在于操作系统的缓存中。

  相反,把日志刷新到持久化存储意味着InnoDB请求操作系统把数据刷出缓存,并且确认写到磁盘了,这是一个阻塞IO的调用,直到数据被完全写回才会完成,当写数据到磁盘比较慢,而该配置项设置为1时,可能明显地降低InnoDB每秒可以提交的事务数。

innodb 是如何刷新和打开日志以及数据文件

  mysql的innodb_flush_method这个参数控制着innodb数据文件及redo log的打开、刷写模式,对于这个参数,文档上是这样描述的:
  有三个值(非window系统):fdatasync(默认),O_DSYNC,O_DIRECT

  1. fdatasync,调用fsync()去刷数据文件与redo log的buffer。
  2. O_DSYNC,innodb会使用O_SYNC方式打开和刷写redo log,使用fsync()刷写数据文件。
  3. O_DIRECT,innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo log。

表空间:

  在配置文件(my.cnf)中设置: innodb_file_per_table

优点:

  1. 每个表都有自已独立的表空间。
  2. 每个表的数据和索引都会存在自已的表空间中。
  3. 可以实现单表在不同的数据库中移动。
  4. 空间可以回收(除drop table操作处,表空不能自已回收)
    a.Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb;回缩不用的空间。
    b.对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。
    c.对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。

缺点:

  1. 相比较之下,使用独占表空间的效率以及性能会更高一点。

双写缓冲:

  先简单解释下什么是双写缓冲。InnoDB使用了一种叫做doublewrite的特殊文件flush技术,在把pages写到date files之前,InnoDB先把它们写到一个叫doublewrite buffer的连续区域内,在写doublewrite buffer完成后,InnoDB才会把pages写到data file的适当的位置。如果在写page的过程中发生意外崩溃,InnoDB在稍后的恢复过程中在doublewrite buffer中找到完好的page副本用于恢复。

  1. 有些文件系统做了同样的事如zfs文件系统可以设置innodb_doublewrite为0来关闭双写缓冲

其他i/o配置

  1. sync_binlog:如果设置为0默认值是0 mysql不会刷新,如果比0大表示经过几次刷新。
  2. autocommit:0自动提交 每一条语句都是一次写 1 一个事务是一次写
    如果sync_binlog设置不为1 那么数据库崩溃后可能导致数据丢失。

MyISAM的I/O配置

  • MyISAM通常每次写操作之后就把索引变更刷新磁盘,批量操作会更快一些

  • 通过设置delay_key_write变量,可以延迟索引的写入,修改的键缓冲块直到表被关闭才会刷新

  • myisam_recover选项控制MyISAM怎样寻找和修复错误

  • 内存映射使得MyISAM直接通过操作系统的页面缓存访问.MYD文件,避免系统调用的开销,5.1后可以通过myisam_use_mmap选项打开内存映射

配置MySQL并发

InnoDB并发配置

  • InnoDB有自己的“线程调度器”控制线程怎么进入内核访问数据,以及它们在内核中一次可以做哪些事,最基本的限制并发的方式是使用innodb_thread_concurrency变量,它会限制一次性可以有多少线程进入内核。

  • 并发值 = CPU数量 * 磁盘数量 * 2,在实践中使用更小的值会更好一点。

MyISAM并发配置

  • 尽管MyISAM是表级锁,它依然可以一边读取,一边并发追加新行,这种情况下只能读取到查询开始时的所有数据,新插入的数据是不可见的,这样可以避免不一致读。

  • 通过设置concurrent_insert这个变量,可以配置MyISAM打开并发插入。

  • 让INSERT、REPLACE、DELETE、UPDATE语句的优先级比SELECT语句更低,设置low_priority_updates选项就可以。

完成基本配置

  1. tmp_table_size和max_heap_table_size,这两个设置控制使得Memory引擎的内存临时表能使用多大的内存超过这个设置会自动变为MyISAM。

  2. max_connections,这个设置的作用就像一个紧急刹车,以保证服务器不会因应用程序激增的连接而不堪重负,设置得以容纳正常可能达到的负载,并且要足够安全,能保证允许你登录和管理服务器。

  3. thread_cache_size,可以通过观察服务器一段时间的活动,来计算一个有理有据的值通过观察threads_connected 的变化来设置他 threads_connected 在100-175可以设置为100。

  4. table_cache_size,应该被设置得足够大,以避免总是需要重新打开和重新解析表的定义,可能通过观察Open_tables的值及其在一段时间的变化来检查该变量。

安全和稳定的设置

  1. expire_logs_days,如果启用了二进制日志,应该打开这个选项,可以让服务器在指定的天数之后清理旧的二进制日志。

  2. max_allowed_packet,防止服务器发送太大的包,也会控制多大的包可以被接收。

  3. max_connect_errors,如果知道服务器可以充分抵御蛮力攻击,可以把这个值设得非常大,以有效地禁用主机黑名单。

  4. skip_name_resolve,禁用了另一个网络相关和鉴权谁相关的陷阱:DNS查找。

  5. sql_mode,不建议修改。

  6. sysdate_is_now,可能导致与应用预期向后不兼容的选项。

  7. read_only,禁止没有特权的用户在备库做变更,只接受从主库传输过来的变更,不接受从应用来的变更,可以把备库设置为只读模式。

  8. s kip_slave_start,阻止MySQL试图自动启动复制。

  9. slave_net_timeout,控制备库发现跟主库的连接已经失败并且需要重连之前等待的时间,设置为一分钟或更短。

  10. sync_master_info、sync_relay_log、sync_relay_log_info,5.5以后版本可用,解决了复制中备库长期存在的问题:不把它们的状态文件同步到磁盘,所以服务器崩溃后可能需要人来猜测复制的位置实际上在主库是哪个位置,并且可能在中继日志(Relay Log)里有损坏。

高级InnoDB设置

  1. innodb,如果设置为FORCE,只有在InnoDB可以启动时,服务器才会启动。

  2. innodb_autoinc_lock_mode,控制InnoDB如何生成自增主键值。

  3. innodb_buffer_pool_instances,在5.5以后,可以把缓冲池切分为多段,在高负载的多核机器上提升MySQL可扩展性的一个重要方式。

  4. innodb_io_capacity,有时需要把这个设置得相当高,才能稳定地刷新脏页。

  5. innodb_read_io_threads和innodb_write_io_threads,控制有多少后台线程可以被I/O操作使用。

  6. innodb_strict_mode,让MySQL在某些条件下把警告改成抛错,尤其是无效的或者可能有风险的CREATE TABLE选项。

  7. innodb_old_blocks_time,指定一个页面从LRU链表的“年轻”部分转移到“年老”部分之前必须经过的毫秒数,默认为0,设置为1000毫秒(1秒)非常有效。

猜你喜欢

转载自blog.csdn.net/qq_25825923/article/details/84396337
今日推荐