第8章 优化服务器设置
在这一章,我们将解释为这是我的撒旦JFK数据库嘎斯公开就开始打山豆根士大夫 圣诞节复活节是是国家开始大幅机啊可是对方看见噶开暗杀是的JFK开始讲课的感觉爱看书的JFK史蒂夫卡卡萨丁咖啡碱撒快递费始东方会i二位人家儿童科技数据库的房价开始JFK注释MySQL服务器创建一个靠谱的配置文件的过程。这是一个很绕的过程,有很多有意思的关注点和值得关注的思路。关注这些点很有必要,因为创建一个好配置的最快方法不是从学习配置项开始,也不是从问哪个配置项应该怎么设置或者怎么修改开始,更不是从检查服务器行为和询问哪个配置项可以提升性能开始。最好是从理解MySQL内核和行为开始。然后可以利用这些知识来指导配置MySQL。最后,可以将想要的配置和当前配置进行比较,然后纠正重要并且有价值的不同之处。
人们经常问,“我的服务器有32GB内存,12核CPU,怎样配置最好?”很遗憾,问题没这么简单。服务器的配置应该符合它的工作负载、数据,以及应用需求,并不仅仅看硬件的情况。
MySQL有大量可以修改的参数——但不应该随便去修改。通常只需要把基本的项配置正确(大部分情况下只有很少一些参数是真正重要的),应该将更多的时间花在schema的优化、索引,以及查询设计上。在正确地配置了MySQL的基本配置项之后,再花力气去修改其他配置项的收益通常就比较小了。
从另一方面来说,没用的配置导致潜在风险的可能更大。我们碰到过不止一个“高度调优”过的服务器不停地崩溃,停止服务或者运行缓慢,结果都是因为错误的配置导致的。我们将花一点时间来解释为什么会发生这种情况,并且告诉大家什么是不该做的。
那么什么是该做的呢?确保基本的配置是正确的,例如InnoDB的Buffer Pool和日志文件缓存大小,如果想防止出问题(提醒一下,这样做通常不能提升性能——它们只能避免问题),就设置一个比较安全和稳健的值,剩下的配置就不用管了。如果碰到了问题,可以使用第3章提到的技巧小心地进行诊断。如果问题是由于服务器的某部分导致的,而这恰好可以通过某个配置项解决,那么需要做的就是更改配置。
有时候,在某些特定的场景下,也有可能设置某些特殊的配置项会有显著的性能提升。但无论如何,这些特殊的配置项不应该成为服务器基本配置文件的一部分。只有当发现特定的性能问题才应该设置它们。这就是为什么我们不建议通过寻找有问题的地方修改配置项的原因。如果有些地方确实需要提升,也需要在查询响应时间上有所体现。最好是从查询语句和响应时间入手来开始分析问题,而不是通过配置项。这可以节省大量的时间,避免很多的问题。
另一个节省时间和避免麻烦的好办法是使用默认配置,除非是明确地知道默认值会有问题。很多人都是在默认配置下运行的,这种情况非常普遍。这使得默认配置是经过最多实际测试的。对配置项做一些不必要的修改可能会遇到一些意料之外的bug。
8.1 MySQL配置的工作原理#
在讨论如何配置MySQL之前,我们先来解释一下MySQL的配置机制。MySQL对配置要求非常宽松,但是下面这些建议可能会为你节省大量的工作和时间。
首先应该知道的是MySQL从哪里获得配置信息:命令行参数和配置文件。在类UNIX系统中,配置文件的位置一般在*/etc/my.cnf或者/etc/mysql/my.cnf*。如果使用操作系统的启动脚本,这通常是唯一指定配置设置的地方。如果手动启动MySQL,例如在测试安装时,也可以在命令行指定设置。实际上,服务器会读取配置文件的内容,删除所有注释和换行,然后和命令行选项一起处理。
关于术语的说明:因为很多MySQL命令行选项跟服务器变量相同,我们有时把选项和变量替换使用。大部分变量和它们对应的命令行选项名称一样,但是有一些例外。例如,–memlock选项设置了locked_in_memory变量。
任何打算长期使用的设置都应该写到全局配置文件,而不是在命令行特别指定。否则,如果偶然在启动时忘了设置就会有风险。把所有的配置文件放在同一个地方以方便检查也是个好办法。
一定要清楚地知道服务器配置文件的位置!我们见过有些人尝试修改配置文件但是不生效,因为他们修改的并不是服务器读取的文件,例如Debian下,/etc/mysql/my.cnf才是MySQL读取的配置文件,而不是*/etc/my.cnf*。有时候好几个地方都有配置文件,也许是因为之前的系统管理员也没搞清楚情况(因此在各个可能的位置都放了一份)。如果不知道当前使用的配置文件路径,可以尝试下面的操作:
** $ which mysqld**
/usr/sbin/mysqld
** $ /usr/sbin/mysqld --verbose --help | grep -A 1 'Default options'**
Default options are read from the following files in the given order:
/etc/mysql/my.cnf ~/.my.cnf /usr/etc/my.cnf
对于服务器上只有一个MySQL实例的典型安装,这个命令很有用。也可以设计更复杂的配置,但是没有标准的方法告诉你怎么来做。MySQL发行版包含了一个现在废弃了的程序,叫mysqlmanager,可以在一个有多个独立部分的配置文件上运行多个实例。(现在已经被一样古老的mysqld_multi脚本替代。)然而许多操作系统发行版本在启动脚本中并不包含或使用这个程序。实际上,很多系统甚至没有使用MySQL提供的启动脚本。
配置文件通常分成多个部分,每个部分的开头是一个用方括号括起来的分段名称。MySQL程序通常读取跟它同名的分段部分,许多客户端程序还会读取client部分,这是一个存放公用设置的地方。服务器通常读取mysqld这一段。一定要确认配置项放在了文件正确的分段中,否则配置是不会生效的。
8.1.1 语法、作用域和动态性#
配置项设置都使用小写,单词之间用下画线或横线隔开。下面的例子是等价的,并且可能在命令行和配置文件中都看到这两种格式:
/usr/sbin/mysqld --auto-increment-offset=5
/usr/sbin/mysqld --auto-increment-offset=5
我们建议使用一种固定的风格。这样在配置文件中搜索配置项时会容易得多。
配置项可以有多个作用域。有些设置是服务器级的(全局作用域),有些对每个连接是不同的(会话作用域),剩下的一些是对象级的。许多会话级变量跟全局变量相等,可以认为是默认值。如果改变会话级变量,它只影响改动的当前连接,当连接关闭时所有参数变更都会失效。下面有一些例子,你应该清楚这些不同类型的行为:
- query_cache_sizey变量是全局的。
- sort_buffer_sizey变量默认是全局相同的,但是每个线程里也可以设置。
- join_buffer_sizey变量也有全局默认值且每个线程是可以设置的,但是若一个查询中关联多张表,可以为每个关联分配一个关联缓冲(join buffer),所以每个查询可能有多个关联缓冲。
另外,除了在配置文件中设置变量,有很多变量(但不是所有)也可以在服务器运行时修改。MySQL把这些归为动态配置变量。下面的语句展示了动态改变sort_buffer_size的会话值和全局值的不同方式:
图5-1:建立在B-Tree结构(从技术上来说是B+Tree)上的索引
图1-1:MySQL服务器逻辑架构图