当我们的电脑反应变慢的时候,我们总会说,是我们的CPU不够快,内存不足,硬盘读取慢等等。那么对于MySQL服务器来讲,硬件也会在一定程度上影响着MySQL的性能。
当系统繁忙的时候,我们可以监控到系统的CPU和可用内存是非常繁忙的。特别是一些计算密集型的应用,CPU就会越可能的影响整个的性能,成为系统的瓶颈。
我们是选择更多的CPU还是选择更快的CPU呢?
我们通常要选择CPU的频率和CPU的数量。当然了,在完美的情况下,这两者是越大越好。我们想要更高频率的CPU,和更多的CPU数量。但是现实很残酷,领导给到的资金就那么多,不能支持更高的配置,被成本卡在了这里。
1、在解决这个问题前,我们先看一下我们的应用,是CPU密集型么?
对于CPU密集型的应用,往往需要更好的CPU,而不是更多的CPU。这里还有一点需要注意,对于目前版本的MySQL而言,不支持多CPU对于同一SQL做并发处理。也就是说,不管我们是多么简单的SQL还是多么复杂的SQL,我们都只能用到一个CPU的核心进行处理,这时多个CPU对于 提高MySQL的处理效率是没有帮助的。
2、然后我们还要看到另一个问题,我们的系统并发量是如何?
虽然单个SQL无法使用多个CPU资源,但是我们要提高系统的吞吐量或者是并发处理量,这时就需要CPU越多越好。如果说一个CPU在一个时刻能处理一个SQL,那么说我们10个CPU在同一时刻是不是就可以处理10条SQL呢。
我们有个衡量数据库处理能力的指标,QPS:同时处理SQL的数量。这里的QPS是指的每秒钟处理SQL的数量。上面所说并发处理10条SQL可能是在纳秒级的,他们两者有关联,但并不是一回事。一个CPU一秒钟也会处理多条SQL。
MySQL通畅应用在web应用中,这类应用通畅并发量是非常大的。所以说,这种情况下CPU的数量比CPU的频率更加重要了。
3、我们还要考虑所使用的MySQL版本
老版本的MySQL对于多核的支持并不好,MySQL5.0之前的版本,这个限制是非常严重的。而对于MySQL5.6,5.7的版本来说,对于多核CPU的使用有了很大的改善。
内存的大小直接影响了数据库的性能。内存的I/O效率远远高于磁盘,即使是SSD或者是Fusion-IO这样的高速磁盘相比,内存的速率也高得多。所以把数据缓存到内存中进行读取,可以大大提高数据库的性能。
在数据库存储引擎中,MyISAM会把索引缓存到内存中,而数据则通过操作系统进行缓存。InnoDB会同时将索引和数据缓存到内存中,从而提高数据库的效率。
内存虽然是越多越好,但是对于性能的影响也是有限的。我们不能指望增加内存而无限的增加性能。数据库能利用的内存也是有限的,当缓存的数据和磁盘存储的数据一样时,也就是说所有的数据都缓存到内存后,再增加内存也是没有意义了。当然这也不是绝对,多余的内存也会增加操作系统等其他服务的性能。
缓存除了对读有益处,对于写也是有益处的。如果有足够的内存,可以避免CPU对磁盘读取的请求。所有的数据缓存到内存中之后,读取效率是很快的。但是写入是不同的问题,我们迟早要把数据写入到磁盘中。虽然是这样,缓存也是对于写入是有益处的。虽然不能避免写入操作,但是可以把多次写入合并成一次写入进行操作。比如说我们经常会看到浏览量这个值,如果是每浏览一次就写入一次的话,会造成大量的IO操作。我们可以在内存中设立计数器,当计数器累计100以后再往数据库中写入。这样的话就把100次写入变成了1次写入,大大提高了写入效率。
数据库也为我们提供了类似的功能,可以在缓存池中,把对同一数据的多次写操作合并成一次,然后最终写入到磁盘上
当我们工作所需要的热数据的大小远远超过可用内存大小时,I/O就会成为我们的瓶颈。网络也可以看做是另外一种I/O资源。网络对性能的影响往往发生于产生大量查询的时候,特别是当我们是使用MemCahe这种的存储引擎缓存的时候。缓存大量失效时,就会产生大量的网络传输,从而影响服务器性能。
虽然内存性能很重要,并且靠增加内存可以解决大部分的IO问题。但也并不能忽视IO子系统对数据库的影响。有时我们也会牺牲一些内存来换取I/O子系统的性能。因为无论如何我们都要在磁盘上进行持久存储。
磁盘的配置和选择
传统磁盘是最常见的I/O设备,也是使用最多的存储设备。这种设备的特点是 价格低、单盘存储空间大、读写速度相对慢。
对于磁盘的选择我们会考虑以下几个方面
1、存储容量
2、传输速度
3、访问时间
4、主轴转速
5、物理尺寸
什么是RAID?
RAID是磁盘冗余队列的简称
简单来说RAID的作用就是可以把多个容量较小的磁盘组成一个更大的磁盘,并提供数据冗余来保证数据的完整性的技术。
磁盘越小的话,性能会越高,但是相对来说存储空间也会越小。我们可以通过RAID来解决这个问题。
另一方面RAID对于数据进行了冗余,减少了因为传统磁盘的损坏而导致的数据丢失。当然了是否能够进行冗余也需要看我们所使用的RAID级别。
RAID级别
等级 | 特点 | 是否冗余 | 盘数 | 读 | 写 |
---|---|---|---|---|---|
RAID 0 | 便宜、快速、危险 | 否 | N | 快 | 快 |
RAID 1 | 高速读、简单、安全 | 是 | 2 | 快 | 慢 |
RAID 5 | 安全,成本折中 | 是 | N+1 | 快 | 取决于最慢盘 |
RAID 10 | 贵、高速、安全 | 是 | 2N | 快 | 快 |
固态存储相比机械磁盘有更好的随机读写性能。
固态磁盘可以支持更好的并发操作
固态磁盘相较于机械磁盘更容易损坏
SAN(Storage Area Network:存储区域网络)和NAS(Network Attached Storage:网络附属存储)是两种外部文件存储设备加载到服务器上的方法。
SAN:设备通过光纤连接到服务器,设备通过块接口访问,服务器可以将其当做硬盘使用。SAN设备可以承受大量的读写操作、读写I/O可以缓存,可以进行I/O合并,随机读写慢,不如本地RAID访问本地磁盘效率。
NAS:设备通过网络连接,通过基于文件协议如NFS或SMB来访问。因为使用网络传输来访问,通常会有一定的网络延迟
采用高性能和高带宽的网络接口设备和交换机
对多个网卡进行绑定,增强可用性和带宽
尽可能的进行网络隔离
64位的CPU一定要工作在64位的系统下
对于并发比较高的场景CPU数量比频率重要
对于CPU密集型场景和复杂SQL频率比数量重要
选主板所能使用频率最高的内存
内存大小对性能有很重要的影响,内存越多越好
单条内存越大越好
从存储效率上进行排序
PCIe -> SSD ->RAID ->磁盘 -> SAN
MySQL支持多种操作系统,包括我们最熟悉的windows,还有Linux和Unix。这里有一点需要注意,windows下数据库对于大小写不敏感,在Linux下大小写敏感。经常会出现的一个问题就是在windows下可以用的数据库名表名,到了Linux下有问题。我们 可以设置MySQL参数强制名字的大小写,可以避免找不到数据库和表这种问题。
这里简单介绍一些系统参数的优化,想要学习更详细的Linux内容可以看一些相关书籍。之后我会针对Linux也写一些博客
net.core.somaxconn=65535
对于一个tcp连接来说,服务器与客户端之间连接需要进行三次握手来建立网络的连接。当网络连接建立起来之后我们可以通过netstat看到端口的状态从 监听变成了可连接。接着这条链路上就可以进传输数据了。对于一个处于监听状态的端口都有一个自己的监听队列。而这个参数就决定了每个端口监听队列的长度。这个参数的默认值可能会比较小,我们可以改成更大一点的值。与之类似的还有下面两个参数。
net.core.netdev_max_backlog=65535
表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目,一般默认值为128(可能不同的linux系统该数值也不同)
net.ipv4.tcp_max_syn_backlog=65535
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。一般在系统内存比较充足的情况下,可以增大这个参数的赋值
net.ipv4.tcp_fin_timeout
表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_reuse
表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle
表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.core.wmem_default = 256960
默认的TCP数据发送窗口大小(字节)。
net.core.wmem_max = 513920
最大的TCP数据发送窗口(字节)。
net.core.rmem_default = 256960
默认的TCP数据接收窗口大小(字节)。
net.core.rmem_max = 513920
最大的TCP数据接收窗口(字节)。
net.ipv4.tcp_keepalive_time = 1800
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为30分钟。
net.ipv4.tcp_keepalive_probes = 3
#如果对方不予应答,探测包的发送次数
net.ipv4.tcp_keepalive_intvl = 15
#keepalive探测包的发送间隔
kernel.shmmax=15461882265
Linux 内核参数中最重要的参数之一,用于定义单个共享内存段的最大值。这个参数应该设置的足够大,以便能够在一个共享内存段下容纳下整个的Innodb缓冲池的大小。这个值的大小对于64位操作系统,可以取的最大值为物理内存值减掉1byte,建议取值大于物理内存的一半。一般取值大于Innodb缓冲池的大小即可。
vm.swappiness = 0
swappiness,Linux内核参数,控制换出运行时内存的相对权重。swappiness参数值可设置范围在0到100之间。 低参数值会让内核尽量少用交换,更高参数值会使内核更多的去使用交换空间。默认值为60(参考网络资料:当剩余物理内存低于40%(40=100-60)时,开始使用交换空间)。对于大多数操作系统,设置为100可能会影响整体性能,而设置为更低值(甚至为0)则可能减少响应延迟。
在windows下,一般是有两种文件系统可以选择:FAT和NTFS,但是在服务器下面,也只有NTFS一种选择
在Linux下面选择会更加丰富一些,如:EXT3、EXT4、XFS等。这三种文件系统都是有日志功能的,这一点对于数据的安全非常重要。据传XFS这种格式性能要比其他两个更高