简介BenchmarkSQL 是一套开源的数据库性能基准测试工具这份资源为适配达梦数据库的定制版本。它面向数据库管理员、运维工程师和性能测试人员主要解决达梦数据库缺乏标准化压测手段的问题可在接近真实业务的读写混合场景中评估事务吞吐量、响应延迟等指标也为不同数据库间的横向选型对比提供了统一口径。压缩包为 zip 格式仅 3.77MB共 94 个文件包含 Java 源码与编译后 class、可直接运行的 jar 包、SQL 建表与存储过程脚本、Shell 启动脚本、properties 参数配置、XML 构建文件等覆盖 BenchmarkSQL 从环境构建、数据装载、压测执行到结果汇总的完整链路。其中专门为达梦数据库准备了独立配置和 SQL 定义使用者只需按实际环境调整主机、端口与账号信息即可开始测试。已有 799 人浏览学习适合需要快速搭建达梦基准测试环境、做数据库对比评估或希望深入研究 BenchmarkSQL 工作机制的技术人员。1. BenchmarkSQL 达梦版是干什么的从一次信创压测说起信创项目里最头疼的不是选型而是数据库换掉之后原来的压测方案全都作废。PostgreSQL、MySQL 时代我习惯用 BenchmarkSQL 跑 TPC-C 负载但项目切到达梦数据库之后这套工具直接用不了——JDBC 驱动不认、建表语句报错、脚本目录里连达梦的方言文件都没有。BenchmarkSQL 作为数据库测试工具本身不挑数据库前提是有人把驱动和 SQL 方言层适配好。所谓“支持达梦数据库版”就是把 BenchmarkSQL 的 JDBC 连接、建表、数据装载、事务混合脚本全部改成达梦能听懂的语言让同一套 TPC-C 模型能稳定跑在 DM 上。这篇笔记就是围绕这个适配版展开讲清楚原理、落地步骤、常见翻车点和结果验证方法适合正在做达梦适配、需要拿出可信压测数据的开发和 DBA 看。2. 为什么 BenchmarkSQL 要专门适配达梦TPC-C 模型与 JDBC 层的三道坎2.1 TPC-C 负载模型与 BenchmarkSQL 的组成它不只是“压一压”BenchmarkSQL 的本质是 TPC-C 标准的实现。TPC-C 模拟的是一个批发商的订单处理系统包含仓库、区域、客户、订单、订单行等数据表以及五种事务新订单New Order、支付Payment、订单状态查询Order Status、发货Delivery、库存查询Stock Level。这些事务不是均匀分布而是按比例混合比如大约 45% 是新订单、43% 是支付。这样做的目的是让测试负载贴近真实业务系统而不是单纯地塞几条 SELECT 或 UPDATE 去考验数据库。BenchmarkSQL 主要由三部分组成。第一部分是 Java 程序负责解析参数、分配终端Terminal、按固定比例发起事务、统计结果第二部分是 SQL 脚本组包括建表脚本如 sqlTableCreates.sql、建索引脚本、删除表脚本、装载存储过程第三部分是驱动层通过 JDBC 访问目标数据库。它之所以在 PG、MySQL、Oracle 上都能跑是因为这三部分里只有 SQL 脚本和 JDBC URL 是数据库相关的Java 的调度逻辑是通用的。理解了这一点就能明白“支持达梦数据库版”大概率做了什么保留 Java 压测调度核心把 JDBC 驱动换成达梦的把 SQL 脚本改成达梦方言。很多人在第一次接触 BenchmarkSQL 时有个误解以为它只是一个像 SysBench 那样的全自动低代码工具运行一个命令就能出报告。实际上BenchmarkSQL 需要仔细配置 warehouse 数量、终端数、运行时长、事务隔离级别并且要先手动执行建表和装载数据的步骤。它给的不是“一键压测”而是一套可以审计的测试流程。这个区别在达梦适配版里尤其重要——如果你拿原版文档去套达梦版可能在建表阶段就卡住了。2.2 达梦数据库的 JDBC 驱动与 SQL 方言适配的关键在“翻译”而不是重写达梦数据库的 JDBC 驱动是独立的 jar 包驱动类名是 dm.jdbc.driver.DmDriver连接 URL 的典型格式是 jdbc:dm://192.168.1.10:5236。端口默认 5236这一点和 MySQL 的 3306、PG 的 5432 完全不同。把驱动放入 BenchmarkSQL 的 lib 目录后还需要在配置文件中显式指定驱动类名和 URL。仅这一步就足以让原版 BenchmarkSQL 翻车——因为原版的 driver 配置默认是 org.postgresql.Driver 或 com.mysql.cj.jdbc.Driver。比驱动更麻烦的是 SQL 方言。达梦在语法上兼容 Oracle 的很多特征但又保留了自己的特性。举几个常见差异建表自增主键。MySQL 用 AUTO_INCREMENTPostgreSQL 用 SERIAL 或 IDENTITY达梦通常用 IDENTITY(1,1)也可以借助序列加触发器。BenchmarkSQL 的原版建表脚本是 PostgreSQL、MySQL、Oracle 各一份达梦版必须在这些脚本基础上改写否则执行到 CREATE TABLE 就会报语法错误。数据类型命名。达梦能识别 VARCHAR2 和 VARCHAR但某些版本里 VARCHAR2 的语义更接近 Oracle 的变长字符串如果脚本里大量用 TEXT达梦可能需要改成 CLOB 或直接使用 VARCHAR 长度上限。函数和关键字。随机数生成、日期加减等操作不同数据库差异很大。达梦虽然兼容 Oracle 函数但要求函数名后不能省略空括号有些 Oracle 语法还需要改写。这些细碎差异如果不逐项处理数据装载阶段大概率会卡住。所谓“适配版”并不是把整个 BenchmarkSQL 重写一遍而是打一套“翻译补丁”JDBC 驱动换掉、连接 URL 换掉、建表和装载的 SQL 脚本换成达梦方言、dml 脚本里的关键函数换成达梦等价写法。理解了这一点你就能判断手里的适配版质量如何——看 SQL 脚本目录有没有单独的达梦脚本而不是只看 Java 代码是否加了“dm”选项。2.3 选型理由为什么用适配版而不是 SysBench 或自定义脚本有人会问既然适配这么麻烦为什么不直接用 SysBench或者自己写一套 Java/Python 压测脚本这个问题我在实际项目里被问过很多次。SysBench 的强项是 OLTP 读写在单表或多表上的性能测试但它的负载模型是简单混合事务和真实业务订单流程差得很远跑出来的数据在汇报时很难让人信服。自定义脚本更灵活但要复现 TPC-C 的事务比例、事务隔离级别、热数据分布开发量和调优周期都非常可观。我自己曾为了复现一个订单模型写了将近一千行 Python最后发现并发控制不够严谨结果没人敢用。BenchmarkSQL 适配版的价值在于它保留了 TPC-C 的完整事务模型并且经过了原版在多数据库上的大量验证适配者只需要聚焦达梦相关的语法差异而不是重新发明一套压测轮子。审计和价值认可度远高于自写脚本。从投入产出比看哪怕你要花一周时间去调适配版也比花一个月去写脚本再花两周去验证要划算得多。当然选型的前提是手里的适配版是可用的。如果只是把原版 BenchmarkSQL 的 README 改了个标题、加了个达梦的 README但 SQL 脚本没有按达梦改写那这版就是伪适配。拿到源码后第一件事不是编译而是检查 sql/databases/ 目录下是否存在达梦专属子目录以及 lib 里面有没有 dm 的驱动 jar。这一步能筛掉一半以上的“假适配版”。3. 把 BenchmarkSQL 达梦版跑起来从 JDBC 驱动到第一个 TPC-C 报告3.1 环境准备JDK、脚本目录结构与 lib 目录的驱动引入先说环境。BenchmarkSQL 本质是 Java 程序JDK 1.8 及以上都能跑但建议用 1.8 而不是最新版本因为部分旧版脚本对 JDK 17 以上的模块化有兼容问题。操作系统方面Linux 上是常态本文以 CentOS 7 系为例。达梦数据库这边确认版本是 DM8 或以上并且达梦的实例已启动、端口可达。拿到适配版源码后先看目录结构。一个完整的 BenchmarkSQL 目录通常包含这些内容benchmarksql/ 源码目录含 Java 类lib/ 第三方依赖驱动与运行时长所需的 jarrunBenchmark.sh 主测试入口runDatabaseBuild.sh 建库建表与装载数据入口runDatabaseDestroy.sh 清理入口props/ 存放配置文件的模板目录sql/ 存放各数据库方言 SQL 脚本的子目录原版里 sql/ 下面有 sql.common、sql.postgres、sql.mysql 等子目录达梦适配版最常见的改动就是新增 sql/dm 或者在 sql.common 里加了达梦分支。你可以用以下命令快速确认有没有达梦驱动和脚本# 进入适配版根目录 cd benchmarksql # 检查 lib 下是否有达梦 JDBC 驱动 ls -l lib | grep -i dm # 检查 SQL 脚本目录中是否有达梦相关子目录 find sql -type d | grep -i dm如果没有看到 dm 驱动的 jar需要把达梦安装目录下自带的 DmJdbcDriver18.jar版本号因人而异也可能是 dm8 开头的 jar复制到 lib 目录。这一步之后先不要急着跑测试先验证驱动能被 JVM 正确加载java -cp lib/DmJdbcDriver18.jar dm.jdbc.driver.DmDriver正常情况会打印出驱动类的基本信息说明 jar 没问题。如果报 ClassNotFoundException说明驱动 jar 版本不完整或者类名不对。接下来修改脚本权限并准备一个专门的运行用户不推荐用 root 跑压测避免满目红色提示干扰诊断。用 oracle 用户或单独的 dbtest 用户比较合适。3.2 配置 benchmark.properties达梦连接的关键参数与解释BenchmarkSQL 的配置主文件是 benchmark.properties。原版默认只有 PG 和 MySQL 的示例达梦版会额外提供一个 props/dm.properties 之类的模板。如果没有模板自己按以下内容创建一个即可。我一般这样配置# 数据库类型dm达梦 dbdm driverdm.jdbc.driver.DmDriver connjdbc:dm://192.168.1.10:5236 # 达梦会话参数 userSYSDBA passwordSYSDBA_PASSWORD # TPC-C 负载规模 warehouses10 terminals20 runMins10 # 装载数据时并发度 loadWorkers4 # 终端运行时思考时间 timeOfTxn10 # 结果输出目录 resultDir./my_result_%tY%tm%td_%tH%tM%tS # 事务相关 isolationTRANSACTION_READ_COMMITTED对每一项做个说明。dbdm 是适配版新增的数据库类型标识如果你的适配版没有这个值需要检查源码里是否有对应的方言加载逻辑。driver 就是达梦的 JDBC 驱动类名。conn 的格式必须是 jdbc:dm://后跟 IP 和端口很多人把端口漏了或者写成 3306这是最常见的连接失败原因。user/password 用达梦的管理员或可用的业务账号注意 SYSDBA 的默认密码在安装时设置不一定是你熟悉的。warehouses 是仓库数决定了总数据量一般建议至少 10 起步用于压力测试但不想数据集太大时 10 足够。terminals 是并发模拟终端数可以理解为同时有多少个虚拟用户在提交事务这个数直接决定并发压力。runMins 是运行分钟数建议正式压测不低于 10 分钟太短的话热数据分布还没稳定。isolation 我建议先设成 READ_COMMITTED因为达梦默认事务隔离级别是读已提交如果你在配置里写了 SERIALIZABLE 但达梦没有真正启用事务并发时会产生大量阻塞误以为是数据库性能差。配置完成后建议用 grep 检查一遍关键项grep -E ^(db|driver|conn|warehouses|terminals) benchmark.properties确认 driver 和 conn 没有因为我手滑打错字。这一步花不了一分钟却能省掉后面各种黑匣子排查时间。3.3 建表与装载数据跑 runDatabaseBuild 之前先看懂三组 SQL 脚本现在进入建表和装载阶段。运行 runDatabaseBuild.sh 之前先搞清楚它会执行什么。常见做法是脚本会依次读取 sql/common 下的公共脚本和 sql/dm 下的达梦专用脚本执行建库、建表、建索引、装载存储过程的动作。如果你用的适配版没有 sql/dm 目录说明这版适配不完整不建议继续用它做正式测试。用一个具体的达梦建表脚本来举例这是整个适配里最容易出问题的地方。原版 PG 脚本里仓库表是这样写的CREATE TABLE warehouse ( w_id SERIAL PRIMARY KEY, w_ytd DECIMAL(12,2), w_tax DECIMAL(4,2) );SERIAL 在达梦里不被识别。适配后的达梦脚本一般会改成CREATE TABLE warehouse ( w_id INT IDENTITY(1,1) PRIMARY KEY, w_ytd DECIMAL(12,2), w_tax DECIMAL(4,2) );关键差异是 IDENTITY(1,1) 替代了 SERIAL。这是因为达梦兼容 Oracle 的 IDENTITY 语法但不支持 PG 的 SERIAL 关键字。如果你拿到适配版后手动改脚本要注意达梦的 IDENTITY 在 CREATE TABLE 语句里使用时有严格的位置要求一般跟在数据类型之后、约束之前。装载数据这一步更值得注意。BenchmarkSQL 会用存储过程生成数据达梦版要么提供达梦方言的装载存储过程要么通过 JDBC 批处理方式插入。我倾向于检查 sql/dm 下有没有以 load 开头的脚本如果没有说明装载逻辑是 Java 侧通过 JDBC 插入这种情况下 JDBC 驱动的批量插入参数就很重要。达梦的 JDBC 驱动默认批量插入可能需要显式开启 rewriteBatchedStatements 之类的参数具体哪个参数以达梦官方文档为准但在 props 的 conn URL 里预留参数位是明智的。执行下面的命令开始建表与装载./runDatabaseBuild.sh props/dm.properties如果脚本在跑的过程中没有明显报错并且日志末尾出现类似 “Data loaded successfully” 的信息说明建表和装载都通过了。如果中途报错不要急着重跑先去看日志里是 SQL 语法错误还是连接错误。SQL 语法错误说明脚本没适配干净连接错误则需要回查 benchmark.properties。装载完成后可以进到达梦数据库里粗查一下数据量避免后面压测时遇到 INVALID INDEX 之类的诡异问题。我用达梦自带的 disql 连上去执行如下命令SELECT COUNT(*) FROM warehouse;返回的数量应当等于配置的 warehouses 数。如果你配置了 10 个仓库这个表应该精确返回 10 行。如果返回 0 或报错说明建表后装载数据失败需要回头看 runDatabaseBuild 的日志。3.4 执行测试并解读输出runBenchmark 与 result 目录里的报告字段建表装载没问题后就可以正式压测了。执行./runBenchmark.sh props/dm.properties这个命令会拉起配置的 terminals 数量的 Java 终端按 TPC-C 事务比例跑 runMins 分钟结束后把结果写入 resultDir 指定的目录。测试过程中日志会持续打印事务执行情况比如新订单事务的平均响应时间、每分钟事务数TPM。不要盯着实时输出看细节更容易漏掉关键错误。我一般会等测试结束进入它生成的目录里看完整报告。结果目录通常是一个带时间戳的文件夹里面包含一个 result.txt 和若干审计文件。result.txt 里最关键的是这个指标Measured tpmC (NewOrders per minute) 2537.45 Measured tpmTotal 5012.89tpmC 是每分钟新订单事务数也是 TPC-C 标准的权威指标tpmTotal 是所有事务的总数。看报告时不要只看 tpmC还要看有没有 NULL、死锁。如果你的适配版在 result.txt 里通篇都是 NULL 值和 0那说明事务提交逻辑有问题不是压测结果。测试结束后还要做一次清理否则下次建表会由于表已存在而失败./runDatabaseDestroy.sh props/dm.properties这个命令会删除测试相关的表和序列。如果跑完压测不清理下一次 runDatabaseBuild 会非常难堪。当然确认达梦实例里没有其他人在用这套测试库的前提下清理是安全的。如果还要调参重测建议按 5.1 里的做法先 destroy 再 build避免数据残留影响结果。4. 达梦适配的避坑清单连接、建表、并发三类典型翻车记录4.1 ClassNotFoundException 与连接超时JDBC 驱动路径与 URL 格式现象执行 runDatabaseBuild.sh 时日志里抛出“java.lang.ClassNotFoundException: dm.jdbc.driver.DmDriver”或者报连接超时Connection timed out。原因适配版源码里封装了达梦驱动但实际的 dm JDBC jar 没有被放入 lib 目录。还有一类原因是 JDK 版本太新导致驱动 jar 加载时被模块化边界挡住。连接超时则大概率是 URL 格式写错或端口不通。解决先把达梦自带的驱动 jar文件名叫 DmJdbcDriver18.jar 或版本号类似复制到 lib 目录确认路径无误。如果 JDK 太新可以切回 JDK 1.8。连接方面在达梦服务器本地执行命令验证端口开放情况。我在一个项目里遇到过达梦装好了但防火墙没放行 5236 端口导致远端连不上本地却正常这个问题不看网络配置很难发现。注意连接 URL 里不要写多余的反斜杠或空格避免字符集问题。4.2 建表语法报错VARCHAR 与 VARCHAR2、自增主键的达梦写法现象runDatabaseBuild 阶段 CREATE TABLE 语句报错比如“语法分析出错”或“关键字 IDENTITY 无法识别”。日志会指到具体的行号但很多人第一反应是去改 Java 代码这是走偏了。原因原版 BenchmarkSQL 的建表脚本基于 PG 或 MySQL 方言里面可能有 SERIAL、AUTO_INCREMENT、TEXT 类型。达梦不完全兼容这些写法或者是适配版的 SQL 脚本里换错了关键字。解决直接查看 sql/dm 下的建表脚本逐条对比原版脚本。看见 SERIAL 就换成 IDENTITY(1,1)TEXT 换成 VARCHAR 或 CLOB如果存在布尔类型换成 TINYINT 或 NUMBER(1)。改完之后重新执行脚本之前先手工跑一段 SQL 确认语法正确。另外注意达梦里的关键字如 PERCENT、COMMENT 在某些场景有特殊含义字段名不要设置成这些词。改完脚本后不要忘记执行 runDatabaseDestroy 清理残留表会导致后续执行时重新命名冲突。4.3 并发一高就锁等待达梦的会话数、锁超时与 UDATA 空间现象terminals 数调到 50 以上压测日志频繁出现“资源繁忙”“事务等待超时”的错误TPM 数值不升反降甚至直接掉到几百。原因BenchmarkSQL 的终端发起的事务密集度很高达梦的默认锁等待时间可能很短或者数据库的会话数上线不够也可能是 UDATA 表空间不足以支撑大量并发时的 undo 数据。解决分三步处理。第一步调大达梦的会话并发参数比如 MAXSESSIONS、MAX_SESSION_STATEMENTS 等具体以达梦版本为准。第二步把锁等待超时时间调大或用 ALTER SYSTEM 调整死锁检测间隔。第三步检查 UDATA 表空间大小如果剩余空间不足扩展数据文件。还有一点容易被忽略达梦的隔离级别是否真的生效。BenchmarkSQL 在 props 里写一个隔离级别但数据库端没开启对应隔离可能只是表现上一致实际锁行为完全不同。配置完达梦参数后重跑前先用 runDatabaseDestroy 清一次库排除旧数据干扰。我在一个项目里把这几个参数都调了之后TPM 从 800 涨到 4000 多差别非常大。4.4 结果集为 NULL 或 TPM 偏低隔离级别与自动提交的副作用现象压测跑完了result.txt 里的 tpmC 是 0 或所有字段都是 NULL看着像程序没执行成功但日志又没有报错。原因BenchmarkSQL 的 Java 代码里关于事务提交位置的设计依赖数据库的自动提交开关。如果达梦 JDBC 驱动的默认行为是自动提交但压测事务里包含了必须手动提交的多语句事务那么事务的完整性就被破坏了统计结果就会异常。另外隔离级别设置不当也会导致读不到未提交数据或频繁重试拉低 TPM。解决在 benchmark.properties 里把隔离级别明确设置为上层业务常用的级别。我在达梦上常用 TRANSACTION_READ_COMMITTED如果你的适配版带额外的 conn 参数需要检查是否支持类似 reWriteBatchedInserts 的批量插入开关。开启批量写入参数后装载数据的速度更快事务提交的数量也能对上。改完配置后建议先用 2 分钟做一次短时测试确认 result.txt 里的值不为 NULL再跑正式时长。这个验证动作非常值得做能避免压测跑了一小时后才发现结果无效的后悔药场景。5. 验证结果真实性的三个技巧不止是看着 TPM 数字好看5.1 多次运行取中位数手工统计与短时 smoke test跑一次压测就出报告很容易受到数据库缓存、后台任务、网络波动的干扰得出的 TPM 可能远高于实际水平。我通常先做一轮短时压测验证脚本能跑通再连续做三轮正式压测每次时长相同、terminals 相同取 TPM 的中位数作为汇报值。这不是统计学洁癖而是数据库压测本身就有随机性第一轮结果往往会因为索引尚未装载进缓存、统计信息未收集而偏低如果直接取第一次大概率会被业务方当场质疑。短时 smoke test 用 2 分钟正式测试至少 10 分钟批次之间先 destroy 再 build让每次的数据分布一致。5.2 结合系统指标判断瓶颈TOP、IOSTAT 与达梦监控只盯着 BenchmarkSQL 的 result.txt 是不够的。当 TPM 不符合预期时你需要判断瓶颈究竟是并发配置太低还是数据库服务器本身资源不够。我习惯在压测时另开一个终端每隔几秒运行一次 top 和 iostat记录 CPU、内存、磁盘利用率。如果 CPU 已经 100% 但 TPM 还是上不去说明在 CPU 层面遇到瓶颈如果磁盘 util 长期接近 100% 而 CPU 空闲很多那问题就在 IO。达梦自带的监控工具能看活动会话数和锁等待情况压测时把这些数据同步抓下来出现锁风暴时能直接定位到具体会话。5.3 调参进阶从 warehouse 数量到驱动批量参数的配合参数调整不是拍脑袋。基准是 warehouse 数决定数据规模terminals 数决定并发压力。增大 warehouses 会让数据量扩大、索引高度增高但 TPM 可能会下降因为单表扫描变慢增大 terminals 会提升并发争用但过了临界点后 TPM 会掉头向下。我一般用“先固定 warehouses再逐步加 terminals”的方法分别测试 10、20、30、40 个终端的曲线找到拐点。达梦驱动侧还有批量抓取参数可调像 fetchSize 和 batchSize 会影响数据装载阶段的效率进而影响压测稳态的建立。以前我图省事只用默认参数跑一遍就上报结果后来被业务方拿真实业务数据一对比差距太大才明白参数调优是压测过程的一部分不是可有可无的玄学。如果你也是在信创场景下提交报告希望这些经验能让你少走一段弯路帮到你。本文还有配套的精品资源点击获取
