1.1sysbench工具

Sysbench是一个开源的,模块化的多线程性能测试工具,可以用来进行硬件环境性能(CPU、内存、磁盘IO、线程、互斥锁),也可以进行数据库的性能测试。在redhat、centos上sysbench有rpm安装包,但是由于需要支持DM测试,所以我们一般使用源码进行编译。sysbench master分支在GitHub上地址为https://github.com/akopytov/sysbench.git

sysbench master分支默认支持MySQL与PG的性能测试。数据库测试脚本形式是lua脚本,自带oltp测试脚本,脚本位置在src/lua/目录下。所以在使用sysbench源码进行编译测试时,一般做法是将src目录下生成的可执行文件sysbench拷贝至src/lua/目录下运行,这样避免运行时出现找不到某些lua脚本的错误。

sysbench测试数据库性能,测试结果中,最重要的两个指标是tps和qps。

tps,transactions per second,每秒事务数。

qps,queries per second,每秒查询数。

query分为三类,分别是read(简写为r,select操作)、write(简写为w,update、delete和insert操作)、other(简写为o,十五的begin、commit操作)。

sysbench运行时需要的参数比较多,可以使用./sysbench --help查看帮助信息。

1.2sysbench默认测试场景说明

sysbench自带oltp测试脚本,模拟了单个表的查询、更新、删除、插入操作,以主键为过滤条件,表名以sbtest的为前缀,后面加上数字1,2,3等等区分。例如SBTEST1,SBTEST2等等。

表结构如下:

  • id,INTEGER,PRIMARY KEY

  • k,INTERGER,该列上创建索引

  • c,char(120)

  • pad,(60)

事务主要包含一下基本操作:

->point_selects

select c from sbtest where id=?

->simple_ranges

select c from sbstest where id between ? and ?

->sum_ranges

select sum(k) from sbtest where id between ? and ?

->order_rangers

select c from sbtest where id between ? and ? order by c

->distinct_ranges

select distinct c from sbtest where id between ? and ? order by c

->index_updates

update sbtest set k=k+1 where id=?

->non_index_updates

update sbtest set c=? where id=?

->deletes

delete from sbtest where id=?

->inserts

insert into sbtest(id,k,c,pad) values (?,?,?,?)

综上,测试表结构不复杂,事务简单,过滤条件是主键查询。一般常见的测试时单表数据量以十万数量级。所以sysbench的性能测试主要压力在CPU上。

不要随意修改测试场景中的列类型。数据类型在internal/sysbench.sql.lua中完成,function statement_methods.bind_create中进行参数类型设定。分析该处代码,可以得到,sysbench将所有整数型都作为BIGINT除历,所有浮点型都作为DOUBLE处理,所以字符型作为VARCHAR除历,不支持时间、时间戳类型。另外,实际测试过程中大仙,dm的实际类型为int类型时,如果dpi绑定类型为bigint,性能很低,为绑定int性能的1%。所以为了规避这个问题,在实现的时候,参数类型为bigint时,绑定类型设定为int。

1.3sysbench默认测试脚本说明

sysbench的数据库测试脚本在src/lua目录上,以oltp为前缀。脚本是lua脚本,可以自行编辑,编辑保存后不需要编译就可直接使用。(lua目录下有个internal文件夹,里面的lua脚本是数据库测是的SQL API。便阶段,以internal目录下的lua脚本为基础生成h文件,供后续程序编译使用。所以修改internal文件夹下的lua脚本需要重新编译sysbench。)

这些脚本中,oltp_common.lua脚本是最基础的测试脚本,其中定义了表结构,事务的基本操作。其他oltp脚本都是引用oltp_common,将其中query进行组合,实现各种测试场景。最常使用的三个脚本如下、:

oltp_read_write.lua:读写混合性能测试,包含查询,更新,删除,插入操作。

oltp_read_only.lua:读性能测试,包含查询操作。

oltp_wirt_write.lua:写性能测试,包含更新,删除,插入操作。

一般使用oltp_read_write.lua脚本测试数据库的oltp性能,这样就可以既包含读操作,写包含写操作。sysbench使用oltp_read_write.lua脚本测试结果中,qps是tps的20倍。也就是说一个transaction包含20个query操作。这20个query包含14个read,4个write,2个oher,详细情况如下:

->bengin,事务开始,计为1个other

->point_selects,循环10次,计为10个read

->simple_rangers,计为1个read

->sum_ranges,计为1个read

->order_rangers,计为1个read

->distinct_ranges,计为1个read

->index_updates,计为1个write

->non_index_updates,计为1个write

->delete_inserts,包含delete操作,insert操作,计为2个write

->commit,事务结束,计为1个other

简单介绍下oltp_read_write.lua脚本。这个脚本由三部分组成:

  • require部分,引用其他的lua脚本。类似于c语言中头文件引用。oltp_read_write.lua脚本中的函数定义都在oltp_common.lua脚本,所以需要首先引用。

  • prepare_statements部分。这部分测试之前的准备工作,对应与sysbench的测试执行过程中的run命令的initializing worker threads部分,对数据库的操作就是简历session后准备各种操作的语句句柄和参数绑定。

  • event部分。这部分是测试执行的具体步骤,对应与sysbench的测试执行过程中run命令在threads started后开始的操作。反复执行event,统计各种指标。

测试中我们可以修改oltp_read_write.lua脚本,注释某些数据库操作,方便调试。lua脚本采用--注释(哦那个sql脚本中注释方法一样)。

2sysbench测试DM2.1编译支持DM的sysbench

a)安装DM,设置环境变量DM_HOME。

如果dm安装在/opt/dmdbms目录,那么会自动增加一个环境变量DM_HOME=/opt/dmdbms。如果该机器没有安装dm,那么需要设置环境变量DM_HOME.

b)生成配置文件。

进入源码目录,执行./autogen.sh

此步骤出错,说明该系统缺少基本的编译工具,例如automake等等,需要先解决环境问题。

此步骤会生成配置文件configure。

c)执行配置文件。

进入源码目录,执行./configure。根据需要带不同参数

x86平台,如果仅测试dm,命令如下,

./configure --without--mysql --with-dm

arm64平台编译,例如FT Kylin10,需要使用编译命令:

./configure --without--mysql --with-dm --build=aarch64-unknown-linux-gnu

如果要编译debug代码的sysbench,使用--with-debug=yes,例如

./configure --without--mysql --with-dm--with-debug=yes

默认是编译支持mysql和dm测试的。编译mysql需要mysql的动态库和头文件,此时会进行检查。

./configure --with--mysql-includes=/usr/include/mysql --with-mysql-libs=/usr/lib64/mysql/

configure命令还支持很多参数,可以通过命令./configure -help查看

d)编译。

进入源码目录,执行make命令。

编译成功后,在src目录下生成可执行文件sysbench。

将sysbench拷贝到src/lua目录下,然后进入src/lua目录运行sysbench

2.2测试前DM的准备工作

a)ini参数优化

RLOG_CHECH_SPACE=1        #默认值是1ENABLE_SPACELIMIT_CHECK=1  #默认值是1
VM_MEM_HEAP=0              #默认值是0

 `PURGE_DEL_OPT=0            #默认值是0。在性能测试中可能设置为2。但是多次重复测试purge_del_opt设置成2导致数据文件膨胀厉害。

 b)dm.ini中设置MAX_SESSION_STATEMENT

 默认  MAX_SESSION_STATEMENT为100,一般不满足测试场景需求,可能会产生如下错误,

 DM_-606_Stmt handle to the limit the number of statements or system of memory

 设置MAX_SESSION_STATEMENT=1000,如果不够可以继续增加。

 该值表示一个session上的句柄限制。由于sysbench测试的时候是先进行stmt prepare操作,然后进行执行。所以,假设1个事务仅有2个query,测试表共计25个,所以每个session要申请2✖25=50个语句句柄用于测试,这些操作都是在测试线程初始化过程中完成的。默认的oltp_read_write.lua脚本中,一个事务有1个query(注意prepare_delete_inserts是2个query),所以如果25个表测试,那么一个session需要11✖25=275个语句句柄,默认MAX_SESSION_STATEMENT是不够的。

 c)运行sysbench的终端,设置LD_LIBRARY_PATH,添加dm的bin目录。

 export LD_LIBRARY_PATH=$DM_HOME/bin:$LD_LIBRARY_PATH

 sysben测试时候需要依赖dm的dpi驱动,依赖dm的其他库,所以需要设置LD_LIBRARY_PATH

 d)扩充数据文件、日志文件

 小数据量的性能测试场景,为了追求高性能,需要提前扩充数据文件,日志文件。如果是达标长时间测试,为了确保后期性能平稳,可以线进行文件扩充。

2.3测试DM

 下面以测试oltp_read_write.lua脚本为例,注意每个步骤仅最后一个参数不同,分别为prepare run cleanup。在数据准备的基础上,可以反复多次运行测试。

 默认的测试脚本,在正常情况下,各种操作都是成功的,也就是说测试过程不会产生数据库的错误信息,例如违反主键约束这种类型的错误。目前没有实现可以忽略的错误代码这一功能。所以,在实现支持dm测试的时候,遇到数据库报错,日志记录的级别都是FATAL。实际测试过程中,如果遇到测试程序异常中止的,需要根据错误信息排查一下数据库的配置信息,特别是注意某些优化配置在当前测试环境下不合适导致数据库操作失败。

 数据准备:创建测试表,并插入测试数据。

./sysbench oltp_read_write.lua  --tables=25 --table-size=250000 --db-driver=dm --dm-db=localhost:5236 --dm-user=SYSDBA --dm-password=SYSDBA --auto-inc=0 --threads=64 --time=180 --report-intercal=10 prepare

运行测试:执行测试。

./sysbench oltp_read_write.lua  --tables=25 --table-size=250000 --db-driver=dm --dm-db=localhost:5236 --dm-user=SYSDBA --dm-password=SYSDBA --auto-inc=0 --threads=64 --time=180 --report-intercal=10 run

清理数据:删除测试表。

./sysbench oltp_read_write.lua  --tables=25 --table-size=250000 --db-driver=dm --dm-db=localhost:5236 --dm-user=SYSDBA --dm-password=SYSDBA --auto-inc=0 --threads=64 --time=180 --report-intercal=10 cleanup

参数说明:

--threads=64        表示发起64个并发连接

--report-intercal=10        表示每10秒输出一次测试进度报告

--time=180        表示测试总时间为180秒

--db--driver=dm        表示使用dm驱动

--dm-db=localhost:5236        表示dm的连接信息

--dm-user=SYSDBA        表示dm的登录用户名

--dm-password=SYSDBA         表示dm的登陆密码

--table-size=250000        表示每个测试表填充数据量为250000

--tables=25        表示25张表

--auto-inc=0        表示主键是否使用自增列。0表示不使用自增列

2.4补充参数说明

通过./sysbench --help查看参数说明时,没有看到--table-size、--tables、--auto-inc的参数说明,这是为什么呢?

因为这几个不是sysbench的参数,而是oltp_read_write.lua的脚本参数。

而oltp_common.lua脚本(被oltp_read_write.lua引用)中,有如下定义

sysbench.cmdline.options

这里面定义了执行lua脚本时可以传入的参数。例如,定义了

table_size={"Number of rows per table",10000}

前面字符串信息时参数说明,后面是默认值。

因此,在执行该lua脚本时,sysbench可以通过参数--table-size来设置table_size的值。注意出现在命令行中参数名和实际参数码的转换。

定义的参数如下:

sysbench.cmdline.options={

  table_size=

     {"Number of rows per table",10000},

  range_size=

     {"Range size for range SELECT queries",100},

  tables=

     {"Number of tables",1},

  point_selects=

     {"Number of point SELECT queries per transaction",10},

  simple_ranges=

     {"Number of simple range SELECT queries per transaction",1},

  sum_ranges=

     {"Number of SELECT SUN() queries per transaction",1},

  order_ranges=

     {"Number of SELECT ORDER BY queries per transaction",1},

  distinct_ranges=

     {"Number of SELECT DISTINCT queries per transaction",1},

  index_updates=

     {"Number of UPDATE index queries per transaction",1},

  non_index_updates=

     {"Number of DELETE/INSERT combinations per transaction",1},

  delete_inserts=

     {"Number of DELETE/INSERT combinations per transaction",1},

  range_selects=

     {"Enable/disable all range SELECT queries",true},

  auto_inc=

  {"Use AUTO_INCREMENT column as Primary Key (for MySQL),"..

     "or its alternatives in other DBMS. When disabled,use "..

     "client-generated IDs",true},

  create_table_options=

     {"Extra CREATE TABLE options", ""},

  skip_trx=

    {"Don't start explicit transactions and execute all queries"..

        "in the AUTOCOMMIT mode",false},

  secondary=

     {"Use a secondary index in place of the PRIMARY KEY",false},

  create_secondary=

     {"Create a secondary index in addition to the PRIMARY KEY",true},

  reconnect=

     {"Reconnect after every N events. The default (0) is to not reconnect",0},

  mysql_storage_engine=

     {"Storage engine, if MySQL is used","innodb"},

  pgsql_variant=

     {"Use this PostgreSQL variant when running with the"..

        "PostgreSQL driver.the only currently supported"..

        "variant is 'redshift'.When enabled,"..

        "create_secondary is automatically disabled,and"..

        "delete_inserts is set to 0"}

}

2.5DM性能指标参考

这里的性能指标,测试场景是小表oltp_read_write.lua脚本测试。此时测试瓶颈主要是CPU。

单机可以用CPU核数来估算最终可能达到的TPS。常规测试经验,基本可以达到单核500TPS,好的情况下可以达到单核600TPS,目前测试最好的情况下达到单核700TPS.FT的cpu性能要弱很多,可以达到单核200TPS.

如何查看测试机器的CPU核数:cat /proc/cpuinfo | grep "processor" | wc -l

3常见问题3.1编译阶段
  • 执行autogen.sh失败

检查是否有可执行权限,如果不是由于权限问题,那么系统缺少基本的编译工具,根据错误信息安装缺少的工具再次尝试。

  • 执行configure失败,错误信息为configure:error:DM_HOME executable not found

编译终端没有设置DM_HOME环境变量。

如果需要编译支持dm的sysbench,根据实际情况,使用export命令设置DM_HOME再次执行configure;否则,在执行configure时候使用参数--without-dm编译不支持dm的sysbench

  • 执行configure失败,错误信息为configure:error:mysql_config executable not found

编译支持mysql的sysbench时,没有找到mysql的头文件和驱动。

如果不需要支持mysql测试,那么configure是使用参数--without -mysql。

如果需要支持mysql测试,那么首先安装mysql-devel软件包,然后configure时使用参数--with-mysql-includes指定mysql头文件目录,--with-mysql-libs指定libmysqlclient.so文件目录。例如

./configure --with mysql-includes=/usr/include/mysql --with-mysql-libs=/usr/lib64/mysql/

  • FT上如何编译sysbench

国产arm64平台上编译sysbench,在configure命令时使用参数--build=aarch64-unknown-linux-gnu,例如

./configure --without-mysql --with-dm --build=aarch64-unknown-linux-gnu

  • 如何编译debug版本的sysbench

configure命令时使用参数--with-debug=yes,例如

./configure --without-mysql --with-dm --with-debug=yes

make步骤最后一步链接出错,错误信息为undefined reference to 'shm_unlink'等等

make步骤,最后一步链接生产sysbench可执行程序出错,具体错误如下:


主要原因时因为DM的dpi驱动后期做了改动,需要新增加一个库,链接命令需要增加-lrt。具体操作步骤


这样就会在src目录下生产sysbench可执行程序了

3.2运行阶段
  • 测试DM,连接失败,错误码为DM_-70089

    错误信息为:ALERT:Error-DM_-70089_Encryption module failed to load

    sysbench测试dm时,未找到所以来的dm动态库

    可以再运行sysbench的终端,设置LD_LIBRARY_PATH,添加dm的bin目录,或者将dm的bin目录下的动态库拷贝到系统库目录。

  • 测试DM,连接成功,测试线程初始化失败,错误码为DM_-606

    错误信息为:DM_-606_Stmt handle to the limit the number of stater

    修改dm.ini,增加AMAX_SESSION_STATEMENT

    该值表示一个session上的句柄限制。由于sysbench测试的时候时先进性stmt prepare操作,然后进行执行。所以假设一个事务仅有2个query,测试表共计25个,所以每个session要申请2*25=50个语句句柄用于测试,这些操作都是在测试线程初始化过程中完成的。默认的oltp_read_write.lua脚本中,一个事务有11个query(注意prepare_delete_inserts时2个query),所以如果25个表测试,那么1个session需要11×25=275个句柄,默认MAX_SESSION_STATEMENT是不够的。

  • 测试DM,连接成功,测试线程初始化失败,错误信息为无效的表或视图名

    首先确认sysbench run之前执行国prepare命令,即确认待测试的dmserber已经完成见表和数据插入操作。其次确认sysbench run使用的参数--tables同prepare过程中使用的--tables参数值一致。

  • 测试DM,测试线程初始化失败,后面有些连接建立失败

    测试的时候,参数--threads决定了此次测试过程中,sysbench会建立多少个数据库连接。例如--threads=64表示会同数据库建立64个session。所以遇到连接建立失败的故障,首先要确认当前dmserver支持的session数目,这由当前达梦数据库版本类型、dmkey、ini中的MAX_SESSIONS共同决定。

  • 测试DM,测试线程初始化失败,错误信息为FATAL:Worker threads failed to initialize within 30 secondssysbench测试中,测试线程初始化的默认超时时间是30秒。当遇到网络延迟,测试表多,测试线程多的时候,完成所有测试线程初始化的时间可能比较长,一旦超过30秒就会出现这个错误。

    此时我们可以在测试命令行中通过参数--thread-init-timeout来设置一个合适的初始化超时时间。

  • 测试DM,在并发量很大,测试表很多的情况下,测试线程初始化失败,错误信息为Error-DM_-70019参考bug 106526,表有250个,并发数为2048.当时的现象是sysbench和dmserver在同一个机器时可以正常进行测试,如果不在同一个机器时就出现无法建立连接的问题。当sysbench和dmserver在不同机器观察的现象是,可以建立1700多个连接,然后后续连接就会失败。分析原因认为是dmserver同时处理太多连接请求,导致每个连接处理耗时增加,后续连接超时了。在dm.ini中增加参数STARTUP_TIMEOUT=500,问题解决。STARTUP_TIMEOUT表示dpi_login发startup和login消息给服务器之间的超时时间。

  • 测试DM过程中出错,错误信息为DM_-7120_Undo record version too old

    dm.ini中UNDO_RETENTION配置的太小导致。增加UNDO_RETENTION。

    一般情况下,为了提高性能,在进行优化配置时,会将UNDO_RETENTION配置的尽可能小,例如UNDO_RETENTION=0.5。但是在实际性能慢的情况下,这种配置可能导致sql执行失败,此时测试无法继续,需要增加UNDO_RETENTION。

  • 使用自增列测试,run过程报错,DM_-2723_Only if specified in the collumn list and SET IDENTITY_INSERT is ON,……

    使用自增列测试,insert语句中包含了自增列的值,导致insert操作失败,测试种中止

    如果使用自增列测试,那么需要修改oltp_common.lua中insert操作的语句和参数绑定,如下

  • 多表,多线程场景下sysbench测试的时候,在线程初始化阶段出现内存不够的错误,导致测试无法进行

    错误信息可能如下,panic unprotected error in call to lua api(not enough memory)

    sysbench在测试多表(100个及以上),多线程(1024个及以上),需要消耗大量物理内存。同时sysbench自带的luajit组件,在内存分配的策略上,也导致在大压力场景下内存分配成倍增加。这些原因导致了sysbench可能出现内存不足的错误。出现这种情况,有可能是sysbench的物理机内存真的不够,也有可能是物理机内存足够,但是sysbench请求的内存超过60G出错。这些错误都和sysbench实现有关,目前无法解决,只能规避。可以采取启动多个sysbench测试的方法绕过。注意,只能拆分并发线程,不能拆分表的数目。也就是说,每个sysbench测试程序使用的表数目一定是测试场景中的表数目,但是测试线程数目可以小于测试场景中的表数目。

    3.3IO密接场景下DM优化

    IO密集场景最大特点是内存不够,无法一次性放入所有数据。由于sysbench的oltp场景下,全部session会无差别访问所有表的数据,所以测试过程中需要平凡读写磁盘。此时影响性能的最重要因素是磁盘的读写能力,而不是CPU能力,或者DM的查询优化能力。在此场景下测试,需要密切关注磁盘的iops,以及每秒读写的数据量。

    IO密集典型场景如下:测试机内存为256G.测试数据138张表,每个表1千万数据,并发线程数目为1024.装载数据后,数据文件大小300G

    3.3.1主要优化点
  • IO相关

    DIRECT_IO=1#磁盘性能高,内存不足,IO密集

    IO_THR_GROUPS=128#磁盘性能高增加IO线程数目

  • 检查点,减少检查点频率,减少每次刷盘数据量CKPT_RLOG_SIZE=0

    CKPT_DIRTY_PAGES=0

    CKPT__FLUSH_RATE=1

    CKPT__INTERVAL=300

  • WORKER_CPU_PERCENT=0,该参数默认值是0

    该参数在性能测试时可能被设置成100,且手册上说0和100是一样的效果。但是实际在kunpeng上测试,WORKER_CPU_PERCENT=0比设成100,tps提示10%

  • 减少UNDO_RETENTION

    减少UNDO_RETENTION=2

  • 索引相关

    主要是因为在prepare阶段后期有并发创建索引的过程。

    #index

    SORT_BUF_SIZE=10

    SORT_BLK_SIZE=1

    SORT_BUF_GLOBAL_SIZE=100000

    SORT_FLAG=1

  • 3.3.2测试注意事项

    控制prepare阶段的并发量。如果并发数量比较大的话,那么在数据插入后,同时创建索引的线程很多,容易产生OOM的错误导致索引创建失败

    在装载数据后如果直接进行测试,那么tps会很低,有可能需要1800秒甚至更长时间才能达到测试峰值

    分析原因,发现在装载数据后直接进行测试,此时检查点多由generated by rlog flush thread产生。如果是正常测试,那么检查点由checkpoint generate by ckpt_interval产生。检查点由generated by rlog flush thread产生,刷盘频率比较快

    3.3.3典型ini参数配置如下

修改ini的sql脚本


sysbench-master简易操作手册

1.    因为sysbench需要dm数据库驱动,因此在执行此工具的机器上必须本地安装dm数据库,不启动服务都可以,sysbench主要是要调用dm数据库安装目录bin下的一个os动态库,不过给出的包已经带有所需的动态库,在/sysbench-master/src/lib64下

2.   安装部署好dm数据库后,把sysbench解压到相关目录下:目录结构最好为

/opt/sysbench-master

3.    进入sysbench-master/src/lua目录下,执行如下脚本进行数据准备:

./sysbench oltp_read_write.lua --tables=25 --table-size=250000 --db-driver=dm --dm-db=localhost:5236 --dm-user=SYSDBA --dm-password=SYSDBA001 --auto-inc=1 --threads=64 --time=180 --report-interval=10 prepare

n  --table-size=250000 表示每个测试表填充数据量为 250000

n  --tables=25表示25张表

n  --threads=64 表示发起64个并发连接

n  --report-interval=10 表示每10秒输出一次测试进度报告

n  --time=180 表示最大执行时长为180秒

4.    上一步prepare执行完毕后,执行如下脚本进行测试:

./sysbench oltp_read_write.lua --tables=25 --table-size=250000 --db-driver=dm --dm-db=localhost:5236 --dm-user=SYSDBA --dm-password=SYSDBA001 --auto-inc=1 --threads=64 --time=180 --report-interval=10 run

5.    上一步run执行完毕后,执行如下脚本进行清楚数据:

./sysbench oltp_read_write.lua --tables=25 --table-size=250000 --db-driver=dm --dm-db=localhost:5236 --dm-user=SYSDBA --dm-password=SYSDBA001 --auto-inc=1 --threads=64 --time=180 --report-interval=10 cleanup

6.   切记,每一次测试都是一个闭环: prepare---run---cleanup,不然会报错,必须严格按照这三步来进行