①CPU
数据库的应用场景一般分为OLTP(Online Transaction Processing,在线事务处理)和OLAP(Online Analytical Processing,在线分析处理),而这两种场景对CPU的要求也会有所差异。OLAP多用在数据仓库或数据集市中,一般需要执行复杂的SQL计算查询;OLTP多用于日常事务处理,如银行交易、电商、Blog以及网络游戏等。InnoDB存储引擎一般都是应用于OLTP的数据库应用,包括以下特点:
高并发
事务处理时间短
查询语句简单且一般都走索引
复杂查询较少
复杂的查询可能需要执行比较、排序以及连接等非常消耗CPU的操作,这些操作在OLTP数据库应用中较少发生。所以,OLTP数据库应用本身对CPU的要求并不是很高。即OLAP是CPU密集型操作,而OLTP是IO密集型操作。不过,多个CPU或者多核CPU对处理大并发量的请求还是会有帮助。如果CPU是多核的,可以修改参数innodb_read_io_threads和innodb_write_io_threads来增加数据库IO线程,以更加充分有效地利用CPU的多核性能。其他的线程,如Purge Thread和Page Cleaner Thread,分别可以通过变量innodb_purge_threads和innodb_page_cleaners设置。
②MEMORY
内存的大小最能直接反映数据库的性能。InnoDB存储引擎既缓存数据页,又缓存索引页,这是一个很大的缓冲池,即InnoDB Buffer Pool。如果缓冲池的大小足够大,以至于可以放下所有的数据文件,这样的数据库性能当然是最优的,所有对数据文件的操作都是在内存中进行的。但这只是理想的情况,实际应用中需要通过预估“活跃”数据的大小来确定数据库服务器内存的大小。如何判断内存的设置已经到了瓶颈?可以通过查看当前服务器的状态,比较物理磁盘的读取和内存读取的比例来判断缓冲池的命中率。通常InnoDB存储引擎缓冲池的命中率不应该小于99%。
mysql> SHOW GLOBAL STATUS LIKE ‘innodb%read%’\G
*************************** 1. row ***************************
Variable_name: Innodb_buffer_pool_read_ahead_rnd
Value: 0
*************************** 2. row ***************************
Variable_name: Innodb_buffer_pool_read_ahead
Value: 0
*************************** 3. row ***************************
Variable_name: Innodb_buffer_pool_read_ahead_evicted
Value: 0
*************************** 4. row ***************************
Variable_name: Innodb_buffer_pool_read_requests
Value: 1543
*************************** 5. row ***************************
Variable_name: Innodb_buffer_pool_reads
Value: 311
*************************** 6. row ***************************
Variable_name: Innodb_data_pending_reads
Value: 0
*************************** 7. row ***************************
Variable_name: Innodb_data_read
Value: 5165568
*************************** 8. row ***************************
Variable_name: Innodb_data_reads
Value: 338
*************************** 9. row ***************************
Variable_name: Innodb_pages_read
Value: 310
*************************** 10. row ***************************
Variable_name: Innodb_rows_read
Value: 8
10 rows in set (0.04 sec)
上述相关参数的具体含义如下:
Innodb_buffer_pool_read_requests:从缓冲池中读取页的次数。
Innodb_buffer_pool_read_ahead:预读的次数。
Innodb_buffer_pool_reads:从物理磁盘读取页的次数。
Innodb_buffer_pool_read_ahead_evicted:预读的页,但是没有被读取就从缓冲池中被替换的页的数量,用来判断预读的效率。
Innodb_data_read:总共读入的字节数。
Innodb_data_reads:发起读取请求的次数,每次读取可能需要读取多个页。
以下公式用于计算各种对缓冲池的操作:
缓冲池命中率 = Innodb_buffer_pool_read_requests / ( Innodb_buffer_pool_read_requests + Innodb_buffer_pool_read_ahead + Innodb_buffer_pool_reads )
[ 即: 缓冲池命中率 = 内存读 / ( 内存读 + 预读 + 磁盘读 ) ]
平均每次读取的字节数 = Innodb_data_read / Innodb_data_reads
即便缓冲池的大小已经大于数据库文件的大小,但并不意味着就没有了磁盘操作。缓冲池只是一个用来存放热点数据的区域,后台线程还会负责将脏页异步刷新回磁盘。除此之外,每次事务提交时还需要将redo log buffer写入重做日志文件。
InnoDB存储引擎缓冲池的配置调整,包含一系列参数。
innodb_buffer_pool_size:缓冲池大小。
innodb_buffer_pool_instances:缓冲池实例个数(默认1个)。
innodb_log_buffer_size:重做日志缓冲大小。
innodb_change_buffer_max_size:Change Buffer可使用缓冲池大小(默认25,表示最多使用1/4的缓冲池空间,最大有效值50)。
innodb_lru_scan_depth:LRU List中页的数量(默认1024)。
innodb_max_dirty_pages_pct:触发Checkpoint的缓冲池脏页大小值(默认75,表示缓冲池中脏页数量占据75%时强制Checkpoint)。
innodb_purge_batch_size:Full Purge时回收的undo页数量。
③DISK
当前大多数数据库系统使用的都是传统的机械磁盘。机械磁盘有两个重要的指标:寻道时间和转速。当前机械硬盘的寻道时间已经能够达到3ms,转速能够达到15000RPM(rotate per minute)。传统机械硬盘的最大问题在于其读写磁头为随机访问。
通常可以将多块机械硬盘组成RAID(Redundant Array of Independent Disks,独立磁盘冗余数组)来提高数据库的性能,也可以将数据文件分布在不同硬盘上来达到负载均衡。对于数据库应用来说,一般RAID 10是最好的选择,虽然需要较多的硬盘,但是它兼顾了RAID 0的速度和RAID 1的安全。
基于闪存(Flash Memory)的SSD(Solid-State Disk,固态硬盘)是一种新的存储设备。不同于机械硬盘,闪存是一个完全的电子设备,具有低延迟性、低功耗以及防震性。需要注意的是,闪存提供的读写速度是非对称的。读取速度要远远快于写入速度。因此,对于固态硬盘在数据库中的应用,应该好好利用其读取的性能,避免过多的写入操作。
可以增加innodb_io_capacity变量的值以充分利用SSD带来的高IOPS。同样,可以关闭刷新邻近页innodb_flush_neighbours为数据库性能带来一定效果的提升。
④OS
操作系统的选择,首先是要使用64位系统和64位的软件。当然,这是以64位的CPU为前提的。具体来说,Linux是MySQL数据库服务器中最常使用的操作系统,因为开源性Linux有着众多的发行版,在选择数据库服务器的Linux版本的时候,需要考虑更多的是其稳定性,而不是新特性。Solaris也是高性能、高可靠的操作系统,其ZFS文件系统非常适合MySQL数据库应用,可以将它的开源版本OpenSolaris作为一种选择。
⑤FS
不同文件系统对数据库性能影响的差异并不明显。对DBA来说,文件系统提供的功能是可以关注的。例如,ZFS文件系统本身就可以支持快照,因此就不需要LVM这样的逻辑卷管理工具了。
内容整理自《MySQL技术内幕 InnoDB存储引擎》(https://book.douban.com/subject/24708143/)。