什么是 TPC-C
TPC-C 是一个对 OLTP(联机交易处理)系统进行测试的规范,使用一个商品销售模型对 OLTP 系统进行测试。详细信息,参考 TPC-C 中文简介。
环境准备
JDK:建议使用 1.8u131 及以上版本。
JDBC:建议使用 mysql-connector-java-5.1.47 版本,其他版本可能存在语法兼容性问题。
Ant:建议使用 apache-ant-1.10 及以上版本。
Benchmark SQL:建议使用 Benchmark SQL 5.0。
OBClient:详细信息,参考 OBClient 文档。
OceanBase 数据库:建议单独部署 ODP。详细信息,参考 在线部署 OceanBase 数据库。
iops:建议磁盘 iops 在 10000 以上。
租户规格:
create resource unit tpcc_unit max_cpu 26, memory_size '70g'; create resource pool tpcc_pool unit = 'tpcc_unit', unit_num = 1, zone_list=('zone1','zone2','zone3'); create tenant tpcc_tenant resource_pool_list=('tpcc_pool'), zone_list('zone1', 'zone2', 'zone3'), primary_zone=RANDOM, locality='F@zone1,F@zone2,F@zone3' set variables ob_compatibility_mode='mysql', ob_tcp_invited_nodes='%';注意
上文的租户规格是基于 OceanBase TPC-C 性能测试报告 中的硬件配置进行配置的,您需根据自身数据库的硬件配置进行动态调整。详细操作,参考 修改租户。
部署集群时,建议不要使用
OBD cluster autodeploy命令,该命令为了保证稳定性,不会最大化资源利用率(例如不会使用所有内存),建议单独对配置文件进行调优,最大化资源利用率。
测试方案
本次测试需要用到 4 台机器,Benchmark SQL、ODP 和 OBD 单独部署在一台机器上,作为客户端的压力机器。通过 OBD 部署 OceanBase 集群需要使用 3 台机器,OceanBase 集群规模为 1:1:1。
说明
在 TPC-C 测试中,部署 Benchmark SQL、ODP 和 OBD 的机器有一定的灵活性,根据 OBServer 总核数的不同分为以下三种情况:
当 OBServer 总核数小于等于 47 核时,该机器仅需要 8 核 64G 即可。
当 OBServer 总核数在 48 核和 72 核之间时,该机器需要 16 核 128G。
当 OBServer 总核数大于等于 73 核时,该机器需要 32 核 128G。
部署成功后,新建执行 TPC-C 测试的租户及用户(sys 租户是管理集群的内置系统租户,请勿直接使用 sys 租户进行测试)。将租户的
primary_zone设置为RANDOM。RANDOM表示新建表分区的 Leader 随机到这 3 台机器。
测试规格
warehouses=1000
loadWorkers=40
terminals=600
runMins=5
newOrderWeight=45
paymentWeight=43
orderStatusWeight=4
deliveryWeight=4
stockLevelWeight=4
OBD 一键测试
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBase.repo
sudo yum install obtpcc java
obd test tpcc obperf --tenant=tpcc_mysql --warehouses 10 --run-mins 1
注意
obd 运行 tpcc,详细参数介绍请参考 obd test tpcc。
在本例中,大幅参数使用的是默认参数,在用户场景下,可以根据自己的具体情况做一些参数上的调整。例如,在本例中使用的集群名为
obperf,租户名是tpcc_mysql。使用 OBD 进行一键测试时,集群的部署必须是由 OBD 进行安装和部署,否则无法获取集群的信息,将导致无法根据集群的配置进行性能调优。
如果系统租户的密码通过终端登陆并修改,非默认空值,则需要您先在终端中将密码修改为默认值,之后通过 obd cluster edit-config 命令在配置文件中为系统租户设置密码,配置项是
# root_password: # root user password。在obd cluster edit-config命令执行结束后,您还需执行obd cluster reload命令使修改生效。运行
obd test tpcc后,系统会详细列出运行步骤和输出,数据量越大耗时越久。obd test tpcc命令会自动完成所有操作,无需其他额外任何操作,包含测试数据的生成、传送、OceanBase 参数优化、加载和测试。当中间环节出错时,您可参考 obd test tpcc 进行重试。例如:跳过数据的生成和传送,直接进行加载和测试。
手动进行 TPC-C 测试
安装 Ant
按照以下步骤安装 Ant:
下载 Ant。
wget "http://archive.apache.org/dist/ant/binaries/apache-ant-1.10.6-bin.zip"安装 Ant
unzip apache-ant-1.10.6-bin.zip设置环境变量。
[admin@obtest004 ~]$ sudo vim /etc/profile #ant export ANT_HOME=xx/apache-ant-1.10.6 export PATH=xx/apache-ant-1.10.6/bin:$PATH [admin@obtest004 ~]$ source /etc/profile检查是否安装成功。
[admin@obtest004 ~]$ant -version如果返回以下信息,则安装成功。
Apache Ant(TM) version 1.10.6 compiled on May 2 2019
安装 Benchmark SQL
按照以下步骤安装 Benchmark SQL:
下载 Benchmark SQL。
详细信息参考 Benchmark SQL 下载地址。
解压 Benchmark SQL。
unzip ./benchmarksql-5.0.zip编译 Benchmark SQL。
进入 Benchmark SQL 解压后的目录,使用 Ant 编译 Benchmark SQL:
[admin@obtest004 ~] $ cd benchmarksql-5.0 [admin@obtest004 benchmarksql-5.0] $ ant
适配 Benchmark SQL5
由于 Benchmark SQL5 不支持 OceanBase 数据库的 TPC-C 测试,本节将详细介绍如何通过修改 BenchMarkSQL5 部分源码支持 OceanBase 数据库。
修改
benchmarksql-5.0/src/client/jTPCC.java文件,增加 OceanBase 数据库相关内容。if (iDB.equals("firebird")) dbType = DB_FIREBIRD; else if (iDB.equals("oracle")) dbType = DB_ORACLE; else if (iDB.equals("postgres")) dbType = DB_POSTGRES; else if (iDB.equals("oceanbase")) ---增加 oceanbase 数据库相关内容 dbType = DB_OCEANBASE; else { log.error("unknown database type '" + iDB + "'"); return; }修改
benchmarksql-5.0/src/client/jTPCCConfig.java文件,增加 OceanBase 数据库类型。public final static int DB_UNKNOWN = 0, DB_FIREBIRD = 1, DB_ORACLE = 2, DB_POSTGRES = 3, DB_OCEANBASE = 4; ---增加 oceanbase 数据库类型修改
benchmarksql-5.0/src/client/jTPCCConnection.java文件,在 SQL 子查询增加 "AS L" 别名。default: stmtStockLevelSelectLow = dbConn.prepareStatement( "SELECT count(*) AS low_stock FROM (" + " SELECT s_w_id, s_i_id, s_quantity " + " FROM bmsql_stock " + " WHERE s_w_id = ? AND s_quantity < ? AND s_i_id IN (" + " SELECT ol_i_id " + " FROM bmsql_district " + " JOIN bmsql_order_line ON ol_w_id = d_w_id " + " AND ol_d_id = d_id " + " AND ol_o_id >= d_next_o_id - 20 " + " AND ol_o_id < d_next_o_id " + " WHERE d_w_id = ? AND d_id = ? " + " ) " + " )AS L"); ---增加 "AS L" 别名 break;重新编译修改后的源码。
[admin@obtest004 ~]# cd benchmarksql-5.0 [admin@obtest004 benchmarksql-5.0]# ant在
benchmarksql-5.0/run目录下,创建文件prop.oceanbase。db=oceanbase driver=com.mysql.jdbc.Driver conn=jdbc:mysql://$host_ip:$port/$db_name?rewriteBatchedStatements=true&allowMultiQueries=true&useLocalSessionState=true&useUnicode=true&characterEncoding=utf-8&socketTimeout=30000000 //请填写完整user信息 user=$user@$tenant password=***** warehouses=1000 loadWorkers=40 terminals=600 database=$db_name //To run specified transactions per terminal- runMins must equal zero runTxnsPerTerminal=0 //To run for specified minutes- runTxnsPerTerminal must equal zero runMins=5 //Number of total transactions per minute limitTxnsPerMin=0 //Set to true to run in 4.x compatible mode. Set to false to use the //entire configured database evenly. terminalWarehouseFixed=true //The following five values must add up to 100 //The default percentages of 45, 43, 4, 4 & 4 match the TPC-C spec newOrderWeight=45 paymentWeight=43 orderStatusWeight=4 deliveryWeight=4 stockLevelWeight=4 // Directory name to create for collecting detailed result data. // Comment this out to suppress. resultDirectory=my_result_%tY-%tm-%td_%tH%tM%tS osCollectorScript=./misc/os_collector_linux.py osCollectorInterval=1 //osCollectorSSHAddr=user@dbhost //osCollectorDevices=net_eth0 blk_sdaprop.oceanbase 中的参数说明:
JDBC 连接串:
conn=jdbc:mysql://x.x.x.x(ip):xx(port)/xxxx(dbname)?rewriteBatchedStatements=true&allowMultiQueries=true&useLocalSessionState=true&useUnicode=true&characterEncoding=utf-8&socketTimeout=3000000rewriteBatchedStatements:
参数非常重要,会严重影响导数据效率,不可以忽略。
如果导数据较慢,可以用对应租户登录上去通过 show full processlist 检查是否开启。
new order 事务中也用到了 batch update,因此导数和 benchmark 阶段都需要开启。
并发数量(terminals):600,MySQL 租户配置下并发需要结合具体配置动态调整。
useLocalSessionState:是否使用 autocommit,read_only 和 transaction isolation 的内部值(jdbc 端的本地值),建议设置为 true,如果设置为 false,则需要发语句到远端请求,增加发送请求频次,影响性能。
warehouses/loadWorkers 这两项用于设置压测数据量,可以适当调整。
numTerminals > 0 && numTerminals <= 10*numWarehouses,terminals 的范围需要在这个区间内。
修改文件:
benchmarksql-5.0/run/funcs.sh,添加 OceanBase 数据库类型。function setCP() { case "$(getProp db)" in firebird) cp="../lib/firebird/*:../lib/*" ;; oracle) cp="../lib/oracle/*" if [ ! -z "${ORACLE_HOME}" -a -d ${ORACLE_HOME}/lib ] ; then cp="${cp}:${ORACLE_HOME}/lib/*" fi cp="${cp}:../lib/*" ;; postgres) cp="../lib/postgres/*:../lib/*" ;; oceanbase) ---添加 OceanBase 数据库类型 cp="../lib/oceanbase/*:../lib/*" ;; esac myCP=".:${cp}:../dist/*" export myCP } ...省略 case "$(getProp db)" in firebird|oracle|postgres|oceanbase) ---添加 OceanBase 数据库类型 ;; "") echo "ERROR: missing db= config option in ${PROPS}" >&2 exit 1 ;; *) echo "ERROR: unsupported database type 'db=$(getProp db)' in ${PROPS}" >&2 exit 1 ;; esac添加 mysql java connector 驱动,推荐 mysql-connector-java-5.1.47.jar。
[admin@obtest004 benchmarksql-5.0]# mkdir lib/oceanbase/ [admin@obtest004 benchmarksql-5.0]# cp xx/mysql-connector-java-5.1.47.jar lib/oceanbase/修改
benchmarksql-5.0/run/runDatabaseBuild.sh。AFTER_LOAD="indexCreates foreignKeys extraHistID buildFinish" # 修改为: AFTER_LOAD="indexCreates buildFinish"改造 BenchMarkSQL5 中的 SQL。
备份并重写
benchmarksql-5.0/run/sql.common/tableCreates.sql。create table bmsql_config ( cfg_name varchar(30) primary key, cfg_value varchar(50) ); create tablegroup if not exists tpcc_group binding true partition by hash partitions 96; create table bmsql_warehouse ( w_id integer not null, w_ytd decimal(12,2), w_tax decimal(4,4), w_name varchar(10), w_street_1 varchar(20), w_street_2 varchar(20), w_city varchar(20), w_state char(2), w_zip char(9), primary key(w_id) )tablegroup='tpcc_group' partition by hash(w_id) partitions 96; create table bmsql_district ( d_w_id integer not null, d_id integer not null, d_ytd decimal(12,2), d_tax decimal(4,4), d_next_o_id integer, d_name varchar(10), d_street_1 varchar(20), d_street_2 varchar(20), d_city varchar(20), d_state char(2), d_zip char(9), PRIMARY KEY (d_w_id, d_id) )tablegroup='tpcc_group' partition by hash(d_w_id) partitions 96; create table bmsql_customer ( c_w_id integer not null, c_d_id integer not null, c_id integer not null, c_discount decimal(4,4), c_credit char(2), c_last varchar(16), c_first varchar(16), c_credit_lim decimal(12,2), c_balance decimal(12,2), c_ytd_payment decimal(12,2), c_payment_cnt integer, c_delivery_cnt integer, c_street_1 varchar(20), c_street_2 varchar(20), c_city varchar(20), c_state char(2), c_zip char(9), c_phone char(16), c_since timestamp, c_middle char(2), c_data varchar(500), PRIMARY KEY (c_w_id, c_d_id, c_id) )tablegroup='tpcc_group' partition by hash(c_w_id) partitions 96; create table bmsql_history ( hist_id integer AUTO_INCREMENT, h_c_id integer, h_c_d_id integer, h_c_w_id integer, h_d_id integer, h_w_id integer, h_date timestamp, h_amount decimal(6,2), h_data varchar(24) )tablegroup='tpcc_group' partition by hash(h_w_id) partitions 96; create table bmsql_new_order ( no_w_id integer not null , no_d_id integer not null, no_o_id integer not null, PRIMARY KEY (no_w_id, no_d_id, no_o_id) )tablegroup='tpcc_group' partition by hash(no_w_id) partitions 96; create table bmsql_oorder ( o_w_id integer not null, o_d_id integer not null, o_id integer not null, o_c_id integer, o_carrier_id integer, o_ol_cnt integer, o_all_local integer, o_entry_d timestamp, PRIMARY KEY (o_w_id, o_d_id, o_id) )tablegroup='tpcc_group' partition by hash(o_w_id) partitions 96; create table bmsql_order_line ( ol_w_id integer not null, ol_d_id integer not null, ol_o_id integer not null, ol_number integer not null, ol_i_id integer not null, ol_delivery_d timestamp, ol_amount decimal(6,2), ol_supply_w_id integer, ol_quantity integer, ol_dist_info char(24), PRIMARY KEY (ol_w_id, ol_d_id, ol_o_id, ol_number) )tablegroup='tpcc_group' partition by hash(ol_w_id) partitions 96; create table bmsql_item ( i_id integer not null, i_name varchar(24), i_price decimal(5,2), i_data varchar(50), i_im_id integer, PRIMARY KEY (i_id) ) ; create table bmsql_stock ( s_w_id integer not null, s_i_id integer not null, s_quantity integer, s_ytd integer, s_order_cnt integer, s_remote_cnt integer, s_data varchar(50), s_dist_01 char(24), s_dist_02 char(24), s_dist_03 char(24), s_dist_04 char(24), s_dist_05 char(24), s_dist_06 char(24), s_dist_07 char(24), s_dist_08 char(24), s_dist_09 char(24), s_dist_10 char(24), PRIMARY KEY (s_w_id, s_i_id) )tablegroup='tpcc_group' partition by hash(s_w_id) partitions 96;备份并重写
benchmarksql-5.0/run/sql.common/tableDrops.sql。drop table bmsql_config; drop table bmsql_new_order; drop table bmsql_order_line; drop table bmsql_oorder; drop table bmsql_history; drop table bmsql_customer; drop table bmsql_stock; drop table bmsql_item; drop table bmsql_district; drop table bmsql_warehouse; drop tablegroup tpcc_group;备份并重写
benchmarksql-5.0/run/sql.common/indexCreates.sql。create index bmsql_customer_idx1 on bmsql_customer (c_w_id, c_d_id, c_last, c_first) local; create index bmsql_oorder_idx1 on bmsql_oorder (o_w_id, o_d_id, o_carrier_id, o_id) local;备份并重写
benchmarksql-5.0/run/sql.common/indexDrops.sql。alter table bmsql_customer drop index bmsql_customer_idx1; alter table bmsql_oorder drop index bmsql_oorder_idx1;
环境调优
ODP 调优,请在 sys 租户下执行。
执行
obclient -h$host_ip -P$host_port -uroot@sys -A命令进入系统租户。alter proxyconfig set automatic_match_work_thread=False; alter proxyconfig set proxy_mem_limited=4G; alter proxyconfig set enable_compression_protocol=False; alter proxyconfig set slow_proxy_process_time_threshold='500ms'; alter proxyconfig set enable_ob_protocol_v2=False; alter proxyconfig set syslog_level='error'OceanBase 数据库导数据阶段,请在 sys 租户下执行。
执行
obclient -h$host_ip -P$host_port -uroot@sys -A命令进入系统租户。alter system set enable_sql_extension=True tenant=<your tenant name>; alter system set enable_sql_audit=false; alter system set enable_early_lock_release=true tenant=<your tenant name>; alter system set memory_chunk_cache_size=0; alter system set syslog_io_bandwidth_limit='30m'; alter system set enable_async_syslog=true; alter system set large_query_worker_percentage=10; alter system set builtin_db_data_verify_cycle=0; alter system set micro_block_merge_verify_level=0; alter system set large_query_threshold='200s'; alter system set trace_log_slow_query_watermark='10s'; alter system set server_permanent_offline_time='36000s'; alter system set _ob_get_gts_ahead_interval='1ms'; alter system set bf_cache_priority=10; alter system set user_block_cache_priority=5; alter system set syslog_level='PERF'; alter system set enable_perf_event=False; alter system set _cache_wash_interval='1m'; alter system set cache_wash_threshold='10G'; alter system set plan_cache_evict_interval='30s'; alter system set bf_cache_miss_count_threshold=1; alter system set _enable_defensive_check=False; alter system set _rowsets_enabled=false tenant=<your tenant name>; alter system set _enable_newsort=false; alter system set _trace_control_info='' tenant=<your tenant name>; alter system set _lcl_op_interval='0ms'; alter system set ob_enable_batched_multi_statement=True tenant=<your tenant name>;说明
在测试结束后,上述参数需要进行恢复,否则在 OBD 升级时,会出现升级报错。
在 OBServer 部署之后,在进行测试 TPCC 的租户下执行。
执行
obclient -h$host_ip -P$host_port -u$user@$tenant -p$password -A命令进入测试租户。set global ob_query_timeout = 3600000000; set global ob_trx_timeout = 3600000000; set global max_allowed_packet = 67108864; set global ob_sql_work_area_percentage = 100; # parallel_servers_target取max_cpu * server_num * 8 set global parallel_servers_target = 624; set global binlog_row_image = 'MINIMAL'; # 导入数据后执行 alter system set writing_throttling_trigger_percentage=100 tenant=<your tenant name>;调优参数设置完毕后请执行
obd cluster restart $cluster_name命令重启集群。
操作步骤
以下命令均在 benchmarksql-5.0/run 目录下执行。按照以下步骤进行 TPC-C 测试:
运行以下命令,初始化环境:
./runDatabaseDestroy.sh prop.oceanbase运行以下命令,创建表并导入数据:
./runDatabaseBuild.sh prop.oceanbase执行合并(需要使用 sys 租户登录)
Major 合并将当前大版本的 SSTable 和 MemTable 与前一个大版本的全量静态数据进行合并,使存储层统计信息更准确,生成的执行计划更稳定。
MySQL [(none)]> use oceanbase Database changed MySQL [oceanbase]> alter system major freeze tenant=<your tenant name>; Query OK, 0 rows affected查看合并是否完成
MySQL [oceanbase]> select FROZEN_SCN, LAST_SCN from oceanbase.CDB_OB_MAJOR_COMPACTION; +---------------------+---------------------+ | FROZEN_SCN | LAST_SCN | +---------------------+---------------------+ | 1667239201167716767 | 1667239201167716767 | | 1667239200111919300 | 1667239200111919300 | | 1667239201167452168 | 1667239201167452168 | | 1667239201168053124 | 1667239201168053124 | | 1667239201167520213 | 1667239201167520213 | +---------------------+---------------------+所有的
FROZEN_SCN和LAST_SCN的值相等即表示合并完成。手动收集统计信息
执行
obclient -h$host_ip -P$host_port -u$user@$tenant -p$password -A -D$database命令进入测试租户。set _force_parallel_query_dop = 96; analyze table bmsql_warehouse partition(bmsql_warehouse) compute statistics for all columns size auto; analyze table bmsql_district partition(bmsql_district) compute statistics for all columns size auto; analyze table bmsql_customer partition(bmsql_customer) compute statistics for all columns size auto; analyze table bmsql_new_order partition(bmsql_new_order) compute statistics for all columns size auto; analyze table bmsql_oorder partition(bmsql_oorder) compute statistics for all columns size auto; analyze table bmsql_order_line partition(bmsql_order_line) compute statistics for all columns size auto; analyze table bmsql_stock partition(bmsql_stock) compute statistics for all columns size auto; analyze table bmsql_history partition(bmsql_history) compute statistics for all columns size auto; analyze table bmsql_config compute statistics for all columns size auto; analyze table bmsql_item compute statistics for all columns size auto;说明
_force_parallel_query_dop可以设置当前 session 上的 query 并发度,取值为 cpu_num。运行以下命令,执行压力测试:
./runBenchmark.sh prop.oceanbase
说明
测试结果可参考 OceanBase TPC-C 性能测试报告。
FAQ
如何停止 Benchmark SQL 工具。
到期自动停止:依赖 prop.oceanbase 中 runMins 设置的值。
强行停止:ps auxf | grep java -- 删除 Java 程删除 runBenchmark 进程。
找不到 main 类型。报错信息如下:
Could not find the main class: ExecJDBC. Program will exit.可能原因有两个:要么升级 JDK,要么升级 JDBC 版本。运行以下命令安装 Java:
sudo yum install jdk终端数量无效。报错信息如下:
Invalid number of terminals!这是 prop.oceanbase 中设置的 terminals 值不对,需填写 numTerminals <= 0 || numTerminals > 10*numWarehouses 范围内的 terminals 值。
事务超时。报错信息如下:
transaction timeout需增大超时时间,测试租户下执行
set global ob_query_timeout=36000000000;set global ob_trx_timeout=36000000000。




