亚马逊AWS官方博客

快马加鞭 – MYSQL RDS 写入性能参数优化

Amazon Relational Database Service 也称为 Amazon RDS,是AWS托管的关系型数据库服务。Amazon Relational Database Service (以下简称 RDS) 让您能够在云中轻松设置、操作和扩展关系型数据库,把您从繁琐耗时的管理任务(如硬件预置、数据库设置、修补和备份)中解放出来,让您能专注于自身业务。

如果您的RDS数据库实例在创建时未指定数据库参数组,数据库实例将使用默认的数据库参数组。 每个默认数据库参数组包含数据库引擎默认值和 Amazon RDS 系统默认值,具体根据引擎、计算等级及实例的分配存储空间而定。您也可以根据实际情况,创建新参数组并让您的数据库实例使用新参数组,然后修改参数。本文将就如何通过调整参数来提高MYSQL RDS写入性能进行讨论,希望给您的调优工作带来一点启示。

本文首先会为您介绍修改和显示RDS参数的方法,然后会列出一些与写入性能相关的数据库参数,最后会通过sysbench工具对参数调整效果进行测试。

一、修改和显示RDS参数

在开始介绍一些性能相关参数之前,我们先来介绍一下如何修改和显示RDS的参数。您可以修改客户创建的数据库参数组中的参数值,但不能更改默认数据库参数组中的参数值,所以如果您要修改参数必须先让你的数据库使用自定义的参数组。

 

您可以通过AWS console的RDS部分的参数组界面创建或者修改您的自定义参数组。点击参数组名称链接可以列出所有参数,在此可以筛选和修改相关参数。

 

 

 

我们也可以通过登录数据库使用show  variables命令来查看和修改参数,对于全局参数前面要加global,否则显示的是session级参数,另外我们也可以通过命令修改session级别的参数,只要加上session关键字,如下图所示,我们修改的autocommit参数只对当前session有效,对其他session无影响。

 

 

二、写入性能优化的一些参数

说完了如何修改和查看RDS参数,我们接下来看一下一些和写入性能相关的参数,限于篇幅,我们不能介绍所有的MYSQL参数。

innodb_buffer_pool_size

在MYSQL中buffer pool用来缓存表和索引的数据,以便加速对数据的处理。如果在buffer在pool中无法获取数据(所谓cache miss),那么就会产生磁盘的随机IO请求,这会降低处理速度,所以配置一个合适大小的buffer pool对性能至关重要。RDS中innodb_buffer_pool_size会设置为{DBInstanceClassMemory*3/4}。

我们可以通过show engine innodb status \G和SHOW GLOBAL STATUS命令观察innodb_buffer_pool_size设置是否合适。

通过show engine innodb status \G我们可以看到free buffers、buffer pool hit rate以及evicted without access(数据被加载到buffer pool没有被访问前就又被推出buffer pool)。

  • 如果较长时间内即使业务高峰期,free buffers都很大,buffer pool hit rate 高于99.5%,evicted without access为0,则innodb_buffer_pool_size可能过量设置了。
  • 如果较长时间内尤其业务高峰期,free buffers都很小,buffer pool hit rate 低于99%,evicted without access不为0,则说明innodb_buffer_pool_size设置得太小,需要增大。

 

show global status where variable_name in (‘Innodb_buffer_pool_read_requests’, ‘Innodb_buffer_pool_reads’); 我们可以关注以下数据,来判断innodb_buffer_pool_size设置的是否合适。

  • innodb_buffer_pool_reads表示InnoDB缓冲池无法满足的请求数。需要从磁盘中读取。
  • innodb_buffer_pool_read_requests表示从内存中逻辑读取的请求数。
  • Innodb_buffer_pool_read_requests / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads) * 100 = InnoDB Buffer Pool hit ratio

 

注意:对于 MySQL 5.7,管理 InnoDB 缓冲池的方式当前存在错误https://bugs.mysql.com/bug.php?id=79379。MySQL 5.7 可能将 innodb_buffer_pool_size 参数的值调整为较大的值,这会导致 InnoDB 缓冲池增长得过大并占用过多内存。此效果会导致 MySQL 数据库引擎停止运行或阻止 MySQL 数据库引擎启动。可用内存较少的数据库实例类更易出现此问题。要解决此问题,请将 innodb_buffer_pool_size 参数的值设置为 innodb_buffer_pool_instances 参数值和 innodb_buffer_pool_chunk_size 参数值的积的倍数。例如,您可以将 innodb_buffer_pool_size 参数值设置为 innodb_buffer_pool_instances 参数值和 innodb_buffer_pool_chunk_size 参数值的积的 8 倍,如以下示例所示。

innodb_buffer_pool_chunk_size = 536870912

innodb_buffer_pool_instances = 4

innodb_buffer_pool_size = (536870912 * 4) * 8 = 17179869184

innodb_log_file_size

在mysql 5.5和5.5以前innodb的logfile最大设置为4GB,在5.6以后的版本中innodb_log_file_size * innodb_log_files_in_group(每个log group中日志文件的个数,默认为2)不能超过512GB。innodb的logfile就是事务日志,用来在mysql 崩溃后的恢复,设置合理的大小对于mysql的性能非常重要。logfile大小对于性能的影响主要体现在checkpoint上,对于 checkpoint的原理可以参考相关的关系数据库理论,更大的logfile大小可以减少checkpoint的次数,减少disk I/O,但是也会增加崩溃后恢复时间。

在MYSQL RDS默认参数组中,innodb_log_file_size默认值为134,217,728 (大约128 MB),通常对您的应用来说该数值嫌小。那么设置多大的logfile合适呢? 通常我们建议innodb_log_file_size * innodb_log_files_in_group要可以承载我们业务高峰期一个小时的日志量,我们可以用命令show engine innodb status\G select sleep(60); show engine innodb status\G 计算每分钟的日志量,进而确定参数的合适大小。此外,基于Bug #69477,日志文件大小应该至少是数据库中最大的BLOB的大小的十倍。

 

 

 

5.0以上版本的MYSQL也可以通过以下命令去查询一分钟内生成日志的大小:

show global status like ‘Innodb_os_log_written%’;

 

 

innodb_io_capacity与innodb_io_capacity_max

innodb_io_capacity决定了innodb后台任务(譬如从buffer pool刷新页面或从change pool合并页面)每秒可用的IO操作次数(IOPS)。innodb_io_capacity默认值是200, 可选范围100–18,446,744,073,709,551,615,而innodb_io_capacity_max是当刷新滞后时,后台任务可以执行的最大IOPS,可选范围100–18,446,744,073,709,551,615,如果您设置了innodb_io_capacity但没有设置innodb_io_capacity_max,则innodb_io_capacity_max默认是innodb_io_capacity的两倍,。

关于这两个参数,若你真的需要对它进行调整,最好的方法是要了解系统可以支持多大的 IOPS。对于SSD我们可以设置innodb_io_capacity为1000,虽然可以设置很大值,但是innodb_io_capacity一般很少设置超过20000,除非您已经尝试过较低的值否则不要设置较大的值。

那么我们如何判断脏页刷新不够快呢?我们可以通过SHOW GLOBAL STATUS LIKE ‘Innodb_buffer_pool_%’;命令,如下图所示,脏页在buffer中的百分比就是Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total * 100%

 

  • Innodb_buffer_pool_pages_data 和Innodb_buffer_pool_bytes_data: buffer pool中buffer总数。
  • Innodb_buffer_pool_pages_dirty 和Innodb_buffer_pool_bytes_dirty: buffer pool中脏buffer的数量。
  • Innodb_buffer_pool_pages_total: buffer pool总页数。

如果使用了information_schema,我们也可以通过以下语句来查询

mysql> SELECT dirty.Value AS 'Dirty Pages', total.Value AS 'Total Pages', ROUND(100*dirty.Value/total.Value, 2) AS 'Dirty Pct' FROM (SELECT VARIABLE_VALUE AS Value FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_total') AS total INNER JOIN (SELECT VARIABLE_VALUE AS Value FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty') AS dirty;
+-------------+-------------+-----------+
| Dirty Pages | Total Pages | Dirty Pct |
+-------------+-------------+-----------+
| 0         | 131072        |      0.00 |
+-------------+-------------+-----------+
1 row in set (0.00 sec)

总之,如果脏页占比长时间较高且从监控看IO有较大余裕,则可调大innodb_io_capacity,但不要一下调整过大,要逐步提高。

innodb_flush_log_at_trx_commit

innodb_flush_log_at_trx_commit定义数据库写log buffer到磁盘的频率以及方式 ,磁盘写入会影响性能,故而此参数让您可以在性能和持久性之间做出选择。

  • 如果innodb_flush_log_at_trx_commit设置为0,每秒一次会将log buffer写入log file(这时数据只是从innodb内存到了操作系统的cache,依然没有进入磁盘), log file的flush(刷到磁盘)操作也同时进行。该模式下,在事务提交的时候,不会主动触发写入磁盘的操作。
  • 如果innodb_flush_log_at_trx_commit设置为1,每次事务提交时MySQL都会把log buffer的数据写入log file,并且flush(刷到磁盘)中去。
  • 如果innodb_flush_log_at_trx_commit设置为2,每次事务提交时MySQL都会把log buffer的数据写入log file.但是flush(刷到磁盘)操作并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操作。

当设为0和2的时候,flush操作不能100%保证,所以在崩溃或断电的时候可能会丢失最后一秒的数据,而1是默认也是最安全的设置,保证commit的数据不会丢失。MYSQL RDS默认 innodb_flush_log_at_trx_commit也是1,这会对性能有消极影响但除非您可以接受丢失数据,否则不建议修改。

sync_binlog

sync_binlog 控制 MySQL server 将 binary log 同步到磁盘的频率,MYSQL RDS默认设置为最安全的1,但是同样会对性能有消极影响,除非您可以接受丢失数据,否则不建议修改。

  • sync_binlog=0: MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统崩溃,在binlog_cache中的所有binlog信息都会被丢失。
  • sync_binlog=1: 这是最安全的设置,表示每次事务提交,MySQL都会把binlog刷下去,不过最安全也是性能损耗最大的设置,尤其对高并发的场景sync_binlog设置为0和1之间写入性能相差会很大,甚至达到5倍之多。
  • sync_binlog=N, N 是 0 和1以外的正整数: binary log 会在收集N 个binary log commit groups 之后同步,同样在系统崩溃的时候 ,可能会丢失数据,N越大性能越好但同时丢失数据的风险也越大。

tmp_table_size 与max_heap_table_size

MYSQL在很多场景譬如UNION操作,子查询,排序分组操作中都可能会生成temporary table,我们通过 EXPLAIN 输出执行计划的Extra列可以看到SQL是否使用了temporary table。temporary table的最大大小由tmp_table_size 与max_heap_table_size其中较小的值决定(MYSQL RDS这两个参数默认值都是16777216即16M),temporary table在大小未超过上限时创建在内存中,一旦超过该上限,temporary table就会自动转为磁盘上的表,这将增加磁盘IO和消耗的时间。我们可能都遇到过复杂查询执行很长时间,从show full processlist可以看到copying to tmp table on disk的状态,这就说明我们的temporary table超过了上限,转为了磁盘上的表。

我们可以通过命令SHOW GLOBAL STATUS LIKE ‘Created_tmp%’;查看内存和磁盘中temporary table得数量,我们可以通过 Created_tmp_disk_tables 和 Created_tmp_tables 了解在磁盘中temporary table的比例。

如果您的应用有大量复杂查询,Created_tmp_disk_tables 比例居高不下,IO成为系统瓶颈而内存又有较大余裕,您可以考虑逐步调大tmp_table_size 与max_heap_table_size。但是请注意,这会给内存带来压力,此外,某些场景下,temporary table一定会创建在磁盘而不是内存中,譬如:

  • 表中存在BLOB或文本列。这包括具有字符串值的用户定义变量,依据列值是二进制还是非二进制字符串而分别被视为BLOB或文本列。
  • 在一个GROUP BY或DISTINCT子句中存在大于512字节(二进制字符串)或大于512字符(非二进制字符串)的任何字符串列。
  • 使用UNION或UNION ALL,且选择列表中存在最大长度大于512(二进制字符串为字节,非二进制字符串为字符)的任何字符串列。
  • SHOW列和DESCRIBE语句使用BLOB作为某些列的类型,因此用于结果的临时表是磁盘上的表

 

foreign_key_checks与unique_checks

当我们对MYSQL RDS进行大批量数据导入或加载,尤其涉及大表时,我们可以通过暂时关闭外键和唯一约束检查来提高插入性能,但是这会带来潜在的风险,您务必要确保相应的数据一致和唯一性。否则约束检查不能通过。

我们可以按以下方式进行数据库导入:

SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET AUTOCOMMIT = 0;
... SQL加载语句 ...
SET foreign_key_checks=1;
SET UNIQUE_CHECKS =1;
commit;

Innodb_read_io_threads 和 Innodb_write_io_threads

innodb_read_io_threads and innodb_write_io_threads决定了InnoDB使用多少后台线程来处理各种类型的IO请求。通过这个配置InnoDB可以有更好的扩展性,每个后台进程可以处理256个IO请求,InnoDB希望可以平衡请求的负载。两个参数有效值范围是1-64,默认值是4。参数决定后台进程数,但是linux系统默认会设置innodb_use_native_aio 不为0,启动异步IO,就会突破参数限制

如果您有高端的IO系统,且在SHOW ENGINE INNODB STATUS的输出中看到64 × innodb_read_io_threads的pending read requests,那么提升innodb_read_io_threads的值会对提升性能有帮助。

 

三、测试

3.1 测试环境准备

3.1.1   硬件环境

本次测试将通过sysbench软件对AWS MYSQL5.6 RDS default参数组以及调整后的参数组进行压测,比对调优效果。请注意:sysbench测试是用来辅助我们判断系统性能的一个方法,用您的实际业务进行压测永远更有针对性。而且在性能测试中,不同的资源配置(包括测试客户端,数据库本身以及网络等),参数配置乃至测试流程都会导致不同的结果,所以进行比对分析永远要先统一测试环境、流程才有意义。

随着软件迭代,本文中描述的测试流程可能需要更新,请读者把握测试流程和指标含义,在工作中按实际情况进行调整。

本文所用硬件环境如下:

2个sysbench客户端配置如下:

机型 vCPU 内存(GiB) 磁盘 IOPS
r5.2xlarge EC2 8 64 IO1 SSD 50G 2020

数据库配置如下:数据库开启了multi-AZ,保证数据库高可用,但是会对写入性能有较大影响

数据库 instance class vCPU 内存(GiB) 磁盘 IOPS 多AZ
MYSQL5.6 RDS db.r5.2xlarge 8 64 IO1 SSD 500G 18000

3.1.2 参数调整

根据硬件环境以及测试时产生的日志量,对参数做了针对性调整,有些参数需要数据库重启才能生效,请在执行相应测试步骤前确认参数值。

请注意:下面的参数仅仅针对本测试中的硬件环境和测试工作量负载,并不具有普遍性,请读者理解参数的含义,根据自身环境和工作负载进行相应配置。正如前述,除非您可以接受丢失数据,否则不建议修改innodb_flush_log_at_trx_commit、sync_binlog等参数为了性能而牺牲安全性,所以本次测试没有对这两个参数进行修改,如果您有类似需求,可以根据本文提供的方法自行测试。

参数 默认值 调整后的值
innodb_io_capacity 200 2000
innodb_io_capacity_max 2000 18000
innodb_log_file_size 134217728 4294967296
innodb_read_io_threads 4 8
innodb_write_io_threads 4 8
innodb_flush_log_at_trx_commit 1 1
sync_binlog 1 1
多可用区

 

注意:因为sysbench1.0.18会有大量prepared statement,所以要设置max_prepared_stmt_count为最大值1048576保证测试顺利进行,否则初始化时可能遇到错误FATAL: MySQL error: 1461 “Can’t create more than max_prepared_stmt_count statements (current value: 16382)”

3.1.3 测试环境准备

在2台测试客户端安装sysbench1.0.18

1.从git中下载sysbench

sudo yum install gcc gcc-c++ autoconf automake make libtool bzr mysql-devel git mysql
git clone https://github.com/akopytov/sysbench.git

 

2.打开sysbench目录

cd sysbench

 

3.切换到sysbench 1.0.18版本,运行autogen.sh

git checkout 1.0.18
sudo ./autogen.sh

 

4.编译

sudo ./configure --prefix=/usr --mandir=/usr/share/man
sudo make
sudo make install

3.1.4 打开限制

开始测试前,需要在Sysbench客户端执行 以下配置,告诉Linux kernel可以用所有的CPU cores 去处理 packets(默认只可以用两个),且减少cores 之间的context switching. 这两个设置是为了用更少的Sysbench 客户端达成吞吐目标.( ffffffff表示使用32个核。请根据实际配置修改,例如实际只有8核,则输入ff)

sudo sh -c 'for x in /sys/class/net/eth0/queues/rx-*; do echo ff > $x/rps_cpus; done'
sudo sh -c "echo 32768 > /proc/sys/net/core/rps_sock_flow_entries"
sudo sh -c "echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt"
sudo sh -c "echo 4096 > /sys/class/net/eth0/queues/rx-1/rps_flow_cnt"
vim /etc/security/limits.conf
*                              soft    nofile  65536
*                              hard    nofile  65536
*                              soft    nproc  65536
*                              hard    nproc  65536

 

3.2 测试流程

3.2.1 只读负载测试

测试数据注入

首先通过sysbench客户端在测试数据库上生成测试表,这里生成250个表,每个表有行数25000条,您也可以根据您的目标,调整表的数目和大小,请替换<>之中的各种连接信息,再执行命令,如果您直接从blog拷贝命令请注意格式。后续命令的注意事项相同,将不再赘述

sysbench --db-driver=mysql --mysql-host=<mysql host> --mysql-port=<port> --mysql-user=<username> --mysql-password=<password> --mysql-db=<dbname> --table_size=25000 --tables=250 --events=0 --time=600  oltp_read_only prepare

 

测试

在所有sysbench client同时执行命令模拟负载,每次持续20分钟,同时从console查看数据库CPU,IO,网络等metrics。在这里我们将通过修改num_threads参数连续测试2*32, 2*64,2*128,2*256多种并发连接的场景。

sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=32 --percentile=95 --range_selects=0 --skip-trx=1 --report-interval=20 oltp_read_only run >> <dbname>_read.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=64 --percentile=95 --range_selects=0 --skip-trx=1 --report-interval=20 oltp_read_only run >> <dbname>_read.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=128 --percentile=95 --range_selects=0 --skip-trx=1 --report-interval=20 oltp_read_only run >> <dbname>_read.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=256 --percentile=95 --range_selects=0 --skip-trx=1 --report-interval=20 oltp_read_only run >> <dbname>_read.log

 

清除测试数据

测试后清除数据命令如下:

sysbench --db-driver=mysql --mysql-host=<mysql host> --mysql-port=<port> --mysql-user=<username> --mysql-password=<password> --mysql-db=<dbname> --table_size=25000 --tables=250 --events=0 --time=600  oltp_read_only cleanup

3.2.2 只写负载测试

数据注入
sysbench --db-driver=mysql --mysql-host=<mysql host> --mysql-port=<port> --mysql-user=<username> --mysql-password=<password> --mysql-db=<dbname> --table_size=25000 --tables=250 --events=0 --time=600  oltp_write_only prepare

 

测试

同样地,在所有sysbench client同时执行命令模拟只写负载,每次持续20分钟,同时从console查看数据库CPU,IO,网络等metrics。在这里我们将通过修改num_threads参数连续测试4*32,4*64,4*128和4*256多种并发连接的场景。

sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=32 --percentile=95  --report-interval=20 oltp_write_only run >> <dbname>_write.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=64 --percentile=95  --report-interval=20 oltp_write_only run >> <dbname>_write.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=128 --percentile=95  --report-interval=20 oltp_write_only run >> <dbname>_write.log
  sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=256 --percentile=95  --report-interval=20 oltp_write_only run >> <dbname>_write.log

 

清除测试数据
sysbench --db-driver=mysql --mysql-host=<mysql host> --mysql-port=<port> --mysql-user=<username> --mysql-password=<password> --mysql-db=<dbname> --table_size=25000 --tables=250 --events=0 --time=600  oltp_write_only cleanup

 

3.2.3 读/写混合压力测试

测试数据注入
sysbench --db-driver=mysql --mysql-host=<mysql host> --mysql-port=<port> --mysql-user=<username> --mysql-password=<password> --mysql-db=<dbname> --table_size=25000 --tables=250 --events=0 --time=600  oltp_read_write  prepare

 

测试

同样地,在所有sysbench client同时执行命令模拟读写混合负载,每次持续20分钟,同时从console查看数据库CPU,IO,网络等metrics。在这里我们将通过修改num_threads参数连续测试4*32,4*64,4*128和4*200多种并发连接的场景。

sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=32 --percentile=95  --report-interval=20 oltp_read_write  run >> <dbname>_read_write.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=64 --percentile=95  --report-interval=20 oltp_read_write  run >> <dbname>_read_write.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=128--percentile=95  --report-interval=20 oltp_read_write  run >> <dbname>_read_write.log
sysbench --db-driver=mysql --mysql-host=<mysql host>  --mysql-user=<username> --mysql-password=<password> --mysql-port=<port>  --mysql-db=<dbname>   --table_size=25000 --tables=250 --events=0 --max-time=1200   --threads=200--percentile=95  --report-interval=20 oltp_read_write  run >> <dbname>_read_write.log

 

清除测试数据
sysbench --db-driver=mysql --mysql-host=<mysql host> --mysql-port=<port> --mysql-user=<username> --mysql-password=<password> --mysql-db=<dbname> --table_size=25000 --tables=250 --events=0 --time=600  oltp_read_write cleanup

四、 结果分析

4.1 结果解读

数据库性能测试输出结果中的指标包括:

  • 每秒执行事务数TPS(Transactions Per Second) 数据库每秒执行的事务数,以COMMIT成功次数为准。
    • SysBench标准OLTP读写混合场景中一个事务包含18个读写SQL。
    • SysBench标准OLTP只读场景中一个事务包含14个读SQL(10条主键查询、4条范围查询)。
    • SysBench标准OLTP只写场景中一个事务包含4个写SQL(2条UPDATE、1条DETELE、1条INSERT)。
  • 每秒执行请求数QPS(Queries Per Second) 数据库每秒执行的SQL数。

 

4.2 结果统计

在不同并发连接数下,使用默认参数组和优化参数组的MYSQL RDS只读负载测试数据如下:

64并发 128并发 256并发 512并发
QPS MYSQL RDS默认参数组 125.8K 125K 123.8K 116.8K
QPS MYSQL RDS优化参数组 129.4K 129.8K 123.9K 118.5K
Response time MYSQL RDS默认参数组(ms) 5.08 10.19 20.65 43.73
Response time MYSQL RDS优化参数组(ms) 4.87 9.82 20.6 43.05

在不同并发连接数下,使用默认参数组和优化参数组的MYSQL RDS只写负载测试数据如下:

64并发 128并发 256并发 512并发
TPS MYSQL RDS默认参数组 1723 3025 2252 1554
TPS MYSQL RDS优化参数组 1747 3372 5770 8005
Response time MYSQL RDS默认参数组(ms) 37.09 42.27 113.24 325.31
Response time MYSQL RDS优化参数组(ms) 36.85 37.94 44.29 63.73

在不同并发连接数下,使用默认参数组和优化参数组的MYSQL RDS读/写混合负载测试数据如下:

64并发 128并发 256并发 400并发
TPS MYSQL RDS默认参数组 1360 2128 2430 1863
TPS AWS MYSQLP RDS 1399 2129 2623 2787
QPS MYSQL RDS默认参数组 27.1K 42.5K 48.5K 37.2K
QPS AWS MYSQLP RDS 27.9K 42.6K 52.4K 55.7K
Response time MYSQL RDS默认参数组(ms) 46.94 60.11 105.31 213.54
Response time MYSQL RDS优化参数组(ms) 45.72 59.99 97.42 142.87

 

4.3 结论

通过以上测试数据,我们可以发现:

  • 因为我们调整的参数主要针对写入性能,故而对读取性能影响较小,而对写入性能影响较大 ,这从测试结果中得到了体现。
  • 并发连接越多,优化相关参数对MYSQL RDS写入和读写混合场景下的性能提升越明显,最多时,只写场景下同等负载,优化参数组后RDS的平均响应时间可以缩小到默认参数组RDS平均响应时间的约1/5,TPS可以提升到默认参数组TPS的约5倍。
  • 同理,对于读写混合场景,当并发数较大或者说写入负载达到一定量时,参数调整的效果才可以展现出来,这是因为同样的并发数读写混合场景的写入负载小于只写场景。
  • 测试数据库开启了Multi-AZ以保证安全性,这会对性能产生较大影响,在分析数据时也必须考虑。

 

结束语

本文为大家介绍的参数只是MYSQL和性能相关的一部分,数据库性能调优是一个系统工程,修改参数增加写入性能的同时,也可能会影响安全或者额外消耗其他资源,sysbench的测试结果也仅仅是供我们调优的参考之一。故而本文只是起到“抛砖引玉”的作用,希望给大家一些参考,您在实际的调优中还需要根据您应用的实际情况进行调整。

 

附录

Amazon Relational Database Service (RDS)用户指南

MYSQL官方文档

sysybench官方文档

 

本篇作者

吕琳

吕琳,AWS数据库专家架构师,负责基于 AWS 的云计算方案的咨询与架构设计,同时致力于数据库和大数据方面的研究和推广。在加入AWS 之前曾在Oracle担任高级讲师并在Amazon担任高级DBA,在数据库设计运维调优、DR解决方案、大数据以及企业应用等方面有丰富的经验。