由于最近一段时间在针对Oracle、MySQL和PostgreSql数据库的选型技术比较时,需要对它们三者进行单库性能压测比较作为重要判断依据。
1、目标
要求
比较Oracle、Postgres、Mysql、Mycat数据库在100、500、1000、1500、2000、3000用户(线程)并发量的读取驱动基表为100w\500w\1000w\2000w\5000w的三表关联时候各个数据库的性能。
目的
使用测试工具实现虚拟用户并发访问压力测试,要求数据库能系统满足用户并发量在1000以上,并能正常工作。
2、软硬件环境
软硬件配置情况
硬件环境 | 数据库服务器 | 客户端 |
硬件配置 | 虚拟机配置 CPU:16C 内存: 32G. 硬盘:20GB+350G | 虚拟机配置: CPU:6C. 内存: 12G. 硬盘:30GB+200G |
软件环境 | 操作系统: Linux CentOS 7 数据库:Oracle 11g/MySQL5.7/PostgreSql9.6 | 操作系统: Linux CentOS 7 测试工具:jmeter 5.1 JDK 1.8 |
数据库关键参数配置
数据库名称 | Process(个) | Session(个) | Sga/shared_buffers/innodb_buffer_pool_size(MB) | Pga(MB) |
Oracle | 10000 | 15024 | 12288 |
|
Postgres | 10000 |
| 12288 |
|
MySQL | 10000 | 12288 |
3、测试场景示例
项目测试编号 | DB_Perform_1 | |||
测试项目描述 | 并发500个虚拟用户(线程)select into cm_port | |||
前置条件 | select a.name from table1 a,table2 b,table3 c | |||
用例序号 | 输入动作 | 预期结果 | 实际结果 | 是否正常运行 |
001 | 采用jmeter进行jdbc请求配置,然后对系统进行加压:任务DB_Perform_1持续时间10分钟,用户(线程)数量为500个 | 500个用户(线程)并发插入端子表数据平均消耗时间<1秒 |
|
|
4、故障描述
在同事测试完成后,输出的报告情况如下截图
显然通过对它们三者之间的比较发现,pg\mysql的差距在最小并发500的时候近20倍,这显然不合乎常理。然后我这边在开始怀疑数据库方面未做参数优化或索引出问题了。
(1)、于是乎我首先对pg展开了缓存参数shared_buffers、max_wal_size和work_mem的优化调整按照实际物理内存分别做了如下调整:
shared_buffers的值由8gb调整为12gb、max_wal_size从1gb调整为4gb、work_mem由原来的8mb调整为4mb。
(2)、检查测试人员提供的脚本所用的表索引,重新对表进行索引整理分析。即REINDEX TABLE table_name;
(3)、重启数据库,进行脚本执行计划分析发现整个都属于正常范围。
(4)、重新使用jmeter发起测试发现还是和原来一样,没有大的改善。开始一直怀疑是不是虚拟机资源被争用了等因素,
于是乎我们把jmeter部署到另外一台物理机的构建的虚拟机展开测试,发现依然如故。经过多方查阅资料未发现数据库其他异常或还有其他什么并发参数可优化。测试同事认为数据库不适宜部署在虚拟机上,最好是放在物理机上。但我没做出马上支持的态度,因为我想oracle也是在这台虚拟机展开的测试,效果还可接受。为什么其他两者差距如此几何级的增加,显然暂时可以排除硬件层面的因素了。另外一个理由就是单个查询响应都是毫秒级和执行计划成本都正常的。
(5)、经过下午一番折腾未果,我晚上还是觉得哪里未去看看,于是我又问了测试人员的部署录制场景脚本在那个路径上,我拿着jmeter再测还是这样。抱着看一看的心态我用vi打开.jmx脚本文件翻看时,发现了前面参数指定对应的表,可是query节点中写的却是另外的表,因此我回头检查库里的对应表,发现其中一个索引未建。我把它建立起来,重新再跑jmeter并发压测,发现它的吞吐量和响应时间执行结果都属于正常范围内,然后又看了其他录制脚本都有相同的问题。这下我立马明白为什么后端如何调整都不起作用的缘故,然后我拉起测试人员调整脚本重新发起压测。结果和我预期判断一致,终于解决了困扰一个周末的问题。
通过这次折腾事件,让我认识到做测试时需要留意细节或敢于怀疑尝试的态度,否则这次的问题真相被掩盖住了。
调整测试场景化脚本的正常100w_500并发压测部分结果截图如下: