特性介绍 | MySQL测试框架 MTR 系列教程(四):语法篇

海山数据库(He3DB)源码详解:海山Mysql 自动测试框架MTR 在修改内核代码后,不仅需要测试新增功能,同时也要对原有功能做回归测试,以保证新加代码对原有功能没有影响,这就需要用到MySQL源码自带的测试框架,简称MTR。主要应用于MySQL等相关数据库项目开发测试,对单个功能点或者模块进行正确性和功能性测试,该工具在SQL级别对MySQL进行单元测试。不仅仅能测试SQL语句,也能根据实际需要测试不同启动参数配置的MySQL服务器和客户端从而验证指定的功能逻辑。 阅读详情

作者:卢文双 资深数据库内核研发

序言:

以前对 MySQL 测试框架 MTR 的使用,主要集中于 SQL 正确性验证。近期由于工作需要,深入了解了 MTR 的方方面面,发现 MTR 的能力不仅限于此,还支持单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁等功能,因此,本着分享的精神,将其总结成一个系列。

主要内容如下:

  • 入门篇:工作机制、编译安装、参数、指令示例、推荐用法、添加 case、常见问题、异常调试
  • 进阶篇:高阶用法,包括单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁
  • 源码篇:分析 MTR 的源码
  • 语法篇:单元测试、压力测试、mysqltest 语法、异常调试

由于个人水平有限,所述难免有错误之处,望雅正。

本文是第四篇语法篇。

本文首发于 2023-07-05 21:53:21


MTR 系列基于 MySQL 8.0.29 版本,如有例外,会特别说明。

单元测试

简介

前文「MySQL 测试框架 MTR 系列教程(二):进阶篇 - 内存/线程/代码覆盖率/单元/压力测试」已介绍了单元测试的概念及使用方法,简单回顾一下:

  • MySQL 使用 TAP(Test Anything Protocol) 和 Google Test Framework 来实现单元测试。
    • TAP 是 Perl 与测试模块之间所使用的简单的基于文本的接口。
    • 为了实现 C/C++ 的单元测试,MySQL 开发了一个用于生成 TAP 文本的库libmytap.a,源码路径位于unittest/mytap/。
  • 使用方法:在执行 cmake 的目录执行 make test或make test-unit 指令(内容详细,更推荐)。
  • 注意事项:在执行单元测试时,不建议启用 ASAN,否则会因 ASAN 检测到单元测试代码有内存泄漏而导致 case 失败。

unittest/ 目录介绍:

CMakeLists.txt
examples # 存放单元测试示例
gunit # 存放所有单元测试用例的代码
mytap # 存放 MyTAP 协议代码

如果新加的测试用例与存储引擎或插件有关,则分别存放在unittest/engine_name 和unittest/plugin_name目录或它们的子目录中。

单元测试代码都位于源码目录/unittest/gunit/ 下,其中有文件也有子目录,无论是当前目录还是子目录下的文件,都以xxxxx-t.cc 格式命名,每个xxxxx-t.cc文件都是一个测试 case,编译后都会生成一个二进制文件 bin/xxxxx-t 。

下面举例说明如何添加单元测试 case 。

示例

比如在 源码目录/unittest/gunit/binlogevents/ 目录下创建一个新的测试用例 myprint 。

一、创建文件unittest/gunit/binlogevents/myprint-t.cc,内容如下:

#include <gtest/gtest.h>


namespace binary_log {
namespace unittests {

class MyPrintTest : public ::testing::Test {
 public:
  MyPrintTest() {}

  void TestBody() { // 必须实现该虚函数
      std::cout << "print_test ====>" << std::endl;
      ASSERT_TRUE(true);
  }
};

// 第二个参数是测试用例名字
TEST_F(MyPrintTest, PrintTest) {
  MyPrintTest t;
  t.TestBody();
}

}  // namespace unittests
}  // namespace codecsog

二、修改 unittest/gunit/binlogevents/CMakeLists.txt 文件,添加myprint用例:

......

# Add tests SET(TESTS transaction_payload_codec
  transaction_compression
  transaction_payload_iterator
  gtids
  gno_intervals
  myprint ####### 新加的行
  heartbeat_codec)

......

三、重新执行 cmake(需要设置-DWITH_DEBUG=1 -DWITH_UNIT_TESTS=1)、编译,会生成二进制文件bin/myprint-t。

四、运行make test或make test-unit ,或者直接执行bin/myprint-t ,测试用例 passed :

wslu@ubuntu:/data/work/mysql/mysql-server/console-build-debug$ ./bin/myprint-t
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MyPrintTest
[ RUN      ] MyPrintTest.PrintTest
print_test ====>
[       OK ] MyPrintTest.PrintTest (0 ms)
[----------] 1 test from MyPrintTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (8 ms total)
[  PASSED  ] 1 test.

参考:

代码覆盖率测试

目前涉及 gcov 的程序文件只有 mysys/dbug.cc 文件以及对应的单元测试文件unittest/gunit/dbug-t.cc 。

gcov 的用法就是在编译时添加选项来实现的:

wslu@ubuntu:/data/work/mysql/mysql-server/console-build-debug/mysql-test$ grep "coverage" ../../CMakeLists.txt -nr
1128:  STRING_APPEND(CMAKE_C_FLAGS   " -fprofile-arcs -ftest-coverage -DHAVE_GCOV")
1129:  STRING_APPEND(CMAKE_CXX_FLAGS " -fprofile-arcs -ftest-coverage -DHAVE_GCOV")
1130:  STRING_APPEND(CMAKE_EXE_LINKER_FLAGS " -fprofile-arcs -ftest-coverage -lgcov")

综上,无需自行编写代码覆盖率测试代码。

压力测试

有两个地方涉及压力测试:

一、压力测试 suite 只有两个:

  • stress
  • innodb_stress

如需要添加新 case,参考对应 suite 已有 case 照猫画虎即可,语法可参考下一章节。

二、mysql-stress-test.pl :被 mysql-test-run.pl 调用,参数是--stress。

  stress=ARGS           Run stress test, providing options to
                        mysql-stress-test.pl. Options are separated by comma.

对于 mysql-stress-test.pl ,更便于自定义测试内容,主要包括:

  • --stress-init-file[=path]

    file_name is the location of the file that contains the list of tests to be run once to initialize the database for the testing. If missing, the default file is stress_init.txt in the test suite directory.

  • --stress-tests-file[=file_name]

    Use this option to run the stress tests. file_name is the location of the file that contains the list of tests. If file_name is omitted, the default file is stress-test.txt in the stress suite directory. (See --stress-suite-basedir).

这部分暂未尝试,不做赘述。

SQL 测试 - mtr/mysqltest 语法

之间文章介绍过 mtr 会将 *.test和*.inc等测试 case 的内容传给 mysqltest 来执行。

mysqltest 是 mysql 自带的测试引擎, 它实现了一种小语言,用来描述测试过程,并将测试结果与预期对比。

本节要讲解 mysqltest 语法格式,你可能会好奇学习这个语法有什么用,为了更直观的说明,首先我们看一下如何编写 mtr 的测试用例。

语法格式

mysqltest 解释的是以.test为后缀的文件(包括其引用的.inc文件)。

mysqltest 小语言按照语法大致分为三类:

  • mysql command :用来控制运行时的行为。一般有两种写法:
command; # 这是后面带;的
--command # 前面带--,不需要;
  • SQL :就是普通的 SQL 语句,测试 case 里大部分是 SQL 语句。
  • comment :注释一般用于描述测试过程,用 # 开头。

示例:借鉴「MySQL 测试框架 MTR 系列教程(一):入门篇」一文中的测试 case(路径是 mysql-test/t/mytest.test ),内容如下:

--echo #
--echo # some comments
--echo #

--disable_warnings
DROP TABLE IF EXISTS t1;
SET @@sql_mode='NO_ENGINE_SUBSTITUTION';
--enable_warnings

SET SQL_WARNINGS=1;

CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);
SELECT * FROM t1;
DROP TABLE t1;

command 列表

mysqltest 提供了几十个 command,本文只介绍最常用的,更多内容请查阅官方手册:MySQL: mysqltest Language Reference 。

error 处理预期错误

语法:

error error_code [, error_code] ...
sql_statements

有些 CASE 就是要验证 sql 失败的情况,在 sql 语句前面加上--error 错误码就可以了。

  • 如果 sql 报错且错误码等于 --error 指定的错误码,mysqltest 不会 abort,而是继续运行。
  • 反之,如果 sql 报错且错误码不等于--error 指定的错误码,mysqltest 会 abort 并报错退出。

--error后面可以跟两种值:一种是error no,另外一种是sqlstate,如果是后者需要加上 S 做前缀。 他们分别是 C API 函数 mysql_errno() 和 mysql_sqlstate() 的返回值。

示例一:使用错误码

--error 1050
create table t1(pk createtime primary key, a int);

等价于

--error ER_TABLE_EXISTS_ERROR
create table t1(pk createtime primary key, a int);

其中数字 1050 对应错误码,ER_TABLE_EXISTS_ERROR 对应错误的逻辑名。

这样在 mysqltest 运行后,会将返回的错误信息一起写入结果文件,这些错误信息就作为期望结果的一部分了。

示例二:使用 SQLSTATE

也可以使用 SQLSTATE 来指示期望有错误返回,例如与 MySQL 错误码 1050 对应的 SQLSTATE 值是 42S01,使用下面的方式,注意编码增加了 S 前缀:

--error S42S01
create table t1(pk createtime primary key, a int);

示例三:指定多个错误码,满足其一则通过

在指令 error 后面是可以加入多个错误码作为参数的,使用逗号分隔即可:

--error 1050,1052
create table t1(pk createtime primary key, a int);

如果该 SQL 报错,若错误码是 1050 或 1051,则符合预期,测试继续。

错误码参考 MySQL 安装包 include 子目录下的 mysqld_error.h 。

disable_abort_on_error / enable_abort_on_error

默认情况下(enable_abort_on_error),sql 执行失败后 mysqltest 就退出了,后面的内容就不会执行,也不会生成 .reject文件。

显示执行disable_abort_on_error命令可以在 sql 失败后继续执行后面的内容,并生成 .reject文件。

--disable_abort_on_error
sql_statements
--enable_abort_on_error

disable_query_log / enable_query_log

默认情况下(enable_query_log),所有的 sql 语句都会记录输出结果。

在一些情况下(比如,使用了循环,query 特别多)不想记录某些 sql 语句及结果,显示调用 disable_query_log 既可。

--disable_query_log
--enable_query_log

其他形如enable_xx/disable_xx的命令还有很多,用法都类似。

connect

创建一个到 mysql server 的新连接并作为当前连接。

语法格式:

connect (name, host_name, user_name, password, db_name [,port_num [,socket [,options [,default_auth [,compression algorithm, [,compression level]]]]]])
  • name is the name for the connection (for use with the connection, disconnect, and dirty_close commands). This name must not already be in use by an open connection.
  • host_name indicates the host where the server is running.
  • user_name and password are the user name and password of the MySQL account to use.
  • db_name is the default database to use. As a special case, NO-ONE means that no default database should be selected. You can also leave db_name blank to select no database.
  • port_num, if given, is the TCP/IP port number to use for the connection. This parameter can be given by using a variable.
  • socket, if given, is the socket file to use for connections to localhost. This parameter can be given by using a variable.
  • options can be one or more of the following words, separated by spaces:
    • CLEARTEXT: Enable use of the cleartext authentication plugin.
    • COMPRESS: Use the compressed client/server protocol, if available.
    • PIPE: Use the named-pipe connection protocol, if available.
    • SHM: Use the shared-memory connection protocol, if available.
    • SOCKET: Use the socket-file connection protocol.
    • SSL:Use SSL network protocol to have encrypted connection.
    • TCP: Use the TCP/IP connection protocol.
      Passing PIPE or SHM on non-Windows systems causes an error, and, similarly, passing SOCKET on Windows systems causes an error.
  • default_auth is the name of an authentication plugin. It is passed to the mysql_options() C API function using the MYSQL_DEFAULT_AUTH option. If mysqltest does not find the plugin, use the –plugin-dir option to specify the directory where the plugin is located.
  • compression algorithm is the name of compression algorithm to be used to compress data transferred between client server. It is passed to the mysql_options() C API function using the MYSQL_OPT_COMPRESSION_ALGORITHMS option.
  • zstd compression level is the extent of compression to be applied when zstd compression algorithm is used. It is passed to the mysql_options() C API function using the MYSQL_OPT_COMPRESSION_ALGORITHMS option.
  • compression level is the extent of compression to be applied based on the compression algorithm used. It is passed to the mysql_options() C API function using the MYSQL_OPT_COMPRESSION_ALGORITHMS option.

示例:

connect (conn1,localhost,root,,);
connect (conn2,localhost,root,mypass,test);
connect (conn1,127.0.0.1,root,,test,$MASTER_MYPORT);

connection

语法:

connection connection_name

选择 connection_name作为当前连接。

示例:

connection master;
connection conn2;
connection default;

disconnect

语法:

disconnect connection_name

关闭连接connection_name 。

示例:

disconnect conn2;
disconnect slave;

测试 session 的时候会用到上述三个命令,以在多个 connection 之间切换。比如:

connect (conn3,127.0.0.1,root,,test,25042);
connection conn3;
create table t1(a int primary key);
drop table t1;
disconnect conn3;

exec

执行 shell 命令。语法:

exec command [arg] ...

示例:

--exec $MYSQL_DUMP --xml --skip-create test
--exec rm $MYSQLTEST_VARDIR/tmp/t1
exec $MYSQL_SHOW test -v -v;

On Cygwin, the command is executed from cmd.exe, so commands such as rm cannot be executed with exec. Use system instead.

perl [terminator]

嵌入 perl 代码,以 EOF 为结束符,也可以自定义结束符。

受限于 mtr 语法,很多操作无法完成,嵌入 perl 脚本可以简化问题。

perl;
  // your perl script
EOF

示例:

perl;
print "This is a test\n";
EOF
perl END_OF_FILE;
print "This is another test\n";
END_OF_FILE

perl 内外的变量交互:

1、可以使用 let 设置环境变量

如果使用 let 时变量名不加 $ 即为设置为环境变量,在 perl 中可以通过 $ENV{'name'} 获取和设置

--let name = "env value"

--perl
  print "name: $ENV{'name'}";
  $ENV{'name'} = 'new env value';
EOF

--echo name: $name

2、在 perl 中拼接 mtr 脚本,然后在 mtr 脚本中执行

perl;
  my $dir = $ENV{'MYSQLTEST_VARDIR'};
  open ( OUTPUT, ">$dir/tmp/name.inc") ;
  print OUTPUT "let \$name = abc;\n";
  close (OUTPUT)
EOF

--source  $MYSQLTEST_VARDIR/tmp/name.inc
--echo $name

vertical_results/horizontal_results

设置 SQL 语句结果的默认显示方式(vertical_results 表示纵向,horizontal_results 表示横向,默认是横向),功能跟 sql 语句的'\G'类似。

示例:

--vertical_results

exit

退出当前测试 case,后续指令不再执行。

let

变量赋值,可支持整数、字符串。

语法:

let $var_name = value
let $var_name = query_get_value(query, col_name, row_num)

示例:

--let $1= 0 # 加 -- 前缀,就不用以分号结尾
let $count= 10;

# 将查询结果赋给变量 q
let $q= `SELECT VERSION()`;

inc/dec

为整数加 1/减 1 。

语法:

inc $var_name/dec $var_name

示例:

--inc $i;
inc $3;

eval

语法:

eval statement

执行sql 语句,支持变量的传递。示例:

eval USE $DB;
eval CHANGE MASTER TO MASTER_PORT=$SLAVE_MYPORT;
eval PREPARE STMT1 FROM "$my_stmt";

query

语法:

query [statement]

显示指定当前语句是 SQL 语句,而不是 command。即使 query 之后是 command(比如sleep),也会当成 statement 来解析。

send

语法:

send [statement]

向 server 发送一条 query,但并不等待结果,而是立即返回,该 query 的结果必须由 reap 指令来接收。

在上一条 query 结果被 reap 指令接收之前,不能向当前 session 发送新的 SQL 语句。

如果 statement 省略了,则执行下一行的 SQL 语句。

示例:

send SELECT 1;

等效于

send;
SELECT 1;

send_eval

语法:

send_eval [statement]

等效于 send + eval ,与send不同在于支持变量传递。

如果 statement 省略了,则执行下一行的 SQL 语句。

示例:

--send_eval $my_stmt

等效于

--send_eval
$my_stmt;

reap

如果当前 session 之前有通过 send 指令向 server 发送 SQL 语句,reap 指令用来接收该 SQL 语句的执行结果。

如果之前没有通过 send 向 server 发送 SQL,则不要执行 reap 指令。

示例:在同一个 session 中用 send 后台执行,用 reap 恢复等待。

--connection 1
--send select sleep(20)

--connection 2
--send select 1

--connection 1
--reap

echo

语法:

echo text

将 text 文本输出到测试 result 中。

示例:

--echo Another sql_mode test
echo should return only 1 row;

query_get_value

语法:

query_get_value(query, col_name, row_num)

获得 query 返回的结果中某行某列的值。

示例:

假如 .test 文件内容如下:

CREATE TABLE t1(a INT, b VARCHAR(255), c DATETIME);
SHOW COLUMNS FROM t1;
let $value= query_get_value(SHOW COLUMNS FROM t1, Type, 1);
echo $value;

输出结果为:

CREATE TABLE t1(a INT, b VARCHAR(255), c DATETIME);
SHOW COLUMNS FROM t1;
Field   Type    Null    Key     Default Extra
a       int(11) YES             NULL
b       varchar(255)    YES             NULL
c       datetime        YES             NULL
int(11)

int(11) 就是 Type 列第一行的值。

source

语法:

source file_name

多个 case 可能共用一块代码,这块代码可以单独放到一个.inc文件,再通过 source 导入。

示例:

--source path/to/script.inc

sleep

语法:

sleep num

Sleep num seconds.

示例:

--sleep 10
sleep 0.5;

replace_column

语法:

replace_column col_num value [col_num value] ...

将下一条语句的结果中的某些列的值进行替换,可以指定多组替换规则,列序号从 1 开始。

示例:

--replace_column 9 #
replace_column 1 b 2 d;

expr 命令 (MySQL 8 之后可用)

语法:

expr $var_name= operand1 operator operand2

对数值变量进行运算,支持 +, -, *, /, %, &&, ||, &, |, ^, <<, >>

--let $val1= 10
--let $var2= 20
--expr $res= $var1 + $var2
--echo $res

在 5.7 版本中用 SQL 语句替代

--let $val1= 10
--let $var2= 20
--expr $res= `select $var1 + $var2`

if

语法:

if (expr)

与其他语言的 if 语句含义相同。

示例:

let $counter= 0;
if ($counter)
{
  echo Counter is not 0;
}

if (!$counter)
{
  echo Counter is 0;
}

while

语法:

while (expr)

与其他语言的 while 语句含义相同。

示例:

let $i=5;
while ($i)
{
  echo $i;
  dec $i;
}

其他命令

其他的命令还有:

assert (expr)

change_user [user_name], [password], [db_name]
character_set charset_name

delimiter str

die [message]
skip [message]

disable_async_client, enable_async_client
disable_connect_log, enable_connect_log
disable_info, enable_info
disable_metadata, enable_metadata
disable_ps_protocol, enable_ps_protocol
disable_query_log, enable_query_log
disable_reconnect, enable_reconnect
disable_result_log, enable_result_log
disable_rpl_parse, enable_rpl_parse
disable_session_track_info, enable_session_track_info
disable_testcase bug_number, enable_testcase
disable_warnings, enable_warnings

end
start_timer
end_timer

# exec command
exec_in_background command [arg] ...
execw command [arg] ...


# 目录相关
force-cpdir src_dir_name dst_dir_name
force-rmdir dir_name
mkdir dir_name
rmdir dir_name
list_files dir_name [pattern]
list_files_append_file file_name dir_name [pattern]
list_files_write_file file_name dir_name [pattern]
# 文件相关
diff_files file_name1 file_name2
remove_files_wildcard dir_name pattern [retry]
write_file file_name [terminator]
append_file file_name [terminator]
cat_file file_name
chmod octal_mode file_name
copy_file from_file to_file [retry]
copy_files_wildcard src_dir_name dst_dir_name pattern [retry]
file_exists file_name [retry]
move_file from_name to_name [retry]
output file_name
remove_file file_name [retry]

# 结果集
lowercase_result
result_format version
sorted_result
partially_sorted_result start_column
query_horizontal statement
query_vertical statement
replace_numeric_round precision
replace_regex /pattern/replacement/[i] ...
replace_result from_val to_val [from_val to_val] ...

# 连接
ping
reset_connection
dirty_close connection_name
send_quit connection
send_shutdown
shutdown_server [timeout]
sync_slave_with_master [connection_name]

# 复制
save_master_pos
sync_with_master offset
wait_for_slave_to_stop

详见官方手册:MySQL: mysqltest Commands

编写规范

  1. 尽可能避免每行超过 80 个字符;
  2. 用#开头,作为注释;
  3. 缩进使用空格,避免使用 tab;
  4. SQL 语句使用相同的风格,包括关键字大写,其它变量、表名、列名等小写;
  5. 增加合适的注释。特别是文件的开头,注释出测试的目的、可能的引用或者修复的 bug 编号;
  6. 为了避免可能的冲突,习惯上表命名使用 t1、t2…,视图命名使用 v1、v2…;

异常调试

本小节已添加到《MySQL 测试框架 MTR 系列教程(一):入门篇》,看过前文的可跳过本节。

分析日志

默认情况下,在目录 mysql-test/var/log/中有日志生成(若指定 --vardir 参数,则以该参数路径为准),分析该日志也能得到一些有用信息。

比如 启动失败,则可以查看 bootstrap.log 文件,去掉命令中的 --bootstrap 并运行即可启动对应的 MySQL 服务来验证、调试。

verbose 参数

启动 mtr 时加 --verbose 参数,定位到引用的脚本位置后可以配置 --echo 命令修改调试。

如果加上 --verbose 打印的内容还不够详细,可以再加一个,即 --verbose --verbose,能打印出 mtr perl 脚本中的日志信息。

示例:

wslu@ubuntu:/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test$ perl mysql-test-run.pl --timer  --force --parallel=1 --vardir=var-rpl --suite=rpl --verbose
Logging: mysql-test-run.pl  --timer --force --parallel=1 --vardir=var-rpl --suite=rpl --verbose
> exe_name: mysqld
MySQL Version 8.0.29
Checking supported features
 - Binaries are debug compiled
> Testing FIPS: --test-ssl-fips-mode 0 error:0F06D065:common libcrypto routines:FIPS_mode_set:fips mode not supported

Using suite(s): rpl
Collecting tests
> Collecting: rpl
> suitedir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl
> testdir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/t
> resdir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/r
> Read combinations file /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/combinations.
 - Adding combinations for rpl
> Collecting: i_rpl
Removing old var directory
> opt_vardir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl
> Removing /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var
> Removing /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/
> Removing /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/
Creating var directory '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl'
> Creating /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl
Installing system database
### safe_path: /data/work/mysql/mysql80-install.bak_asan_ubsan/bin//mysqltest_safe_process --verbose -- /data/work/mysql/mysql80-install.bak_asan_ubsan/bin/mysqld --no-defaults --initialize-insecure --loose-skip-ndbcluster --tmpdir=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/ --core-file --datadir=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/data/ --secure-file-priv=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl --innodb_buffer_pool_size=24M --innodb-log-file-size=5M --innodb_autoextend_increment=8 --character-sets-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/share/charsets --loose-auto_generate_certs=OFF --loose-sha256_password_auto_generate_rsa_keys=OFF --loose-caching_sha2_password_auto_generate_rsa_keys=OFF --init-file=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/bootstrap.sql
Using parallel: 1

==============================================================================
                  TEST NAME                       RESULT  TIME (ms) COMMENT
------------------------------------------------------------------------------
> Client connected
worker[1] > mtr_ping_port: 13000
worker[1] > FREE
worker[1] > mtr_ping_port: 13001
worker[1] > FREE
worker[1] > mtr_ping_port: 13002
worker[1] > FREE
worker[1] > mtr_ping_port: 13003
worker[1] > FREE
......
worker[1] > mtr_ping_port: 13029
worker[1] > FREE
worker[1] > Using MTR_BUILD_THREAD 300, with reserved ports 13000..13029
worker[1] Creating var directory '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl'
worker[1] > result: , file_mode: 0
[  0%] rpl.rpl_atomic_ddl                        [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_atomic_ddl_no_binlog              [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_binlog_cache_encryption           [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_filters_error_cases_on_startup    [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_group_commit_deadlock             [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_group_commit_deadlock_myisam      [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_innodb_auto_increment             [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_killed_ddl                        [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_log_info_repository_persistence_assign_gtids_to_anonymous_transactions  [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_log_info_repository_persistence_require_row  [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_log_info_repository_persistence_require_table_primary_key_check  [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_row_crash_safe                    [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_row_mts_rec_crash_safe            [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_stm_mixed_crash_safe              [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_stm_mixed_mts_rec_crash_safe      [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_stm_mixed_mts_rec_crash_safe_checksum  [ skipped ]  Test needs 'big-test' or 'only-big-test' option.
[  0%] rpl.rpl_io_thd_wait_for_disk_space_stress  [ disabled ]   BUG#23581287 Disabled until bug is fixed.
[  0%] rpl.rpl_writeset_add_unique_key           [ disabled ]   Bug#33134835 RPL_WRITESET_ADD_UNIQUE_KEY FAILS SPORADICALLY
worker[1] > Running test: rpl.rpl_plugin_load
worker[1] > Setting timezone: GMT-3
worker[1] > Cleaning datadirs...
worker[1] > clean_dir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp
worker[1] > unlink: '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/bootstrap.sql'
worker[1] > Generating my.cnf from '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/suite/rpl/my.cnf'
worker[1] > MASTER_MYPORT = 13000
worker[1] > MASTER_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqld.1.sock
worker[1] > MASTER_X_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqlx.1.sock
worker[1] > SLAVE_MYPORT = 13002
worker[1] > SLAVE_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqld.2.sock
worker[1] > SLAVE_X_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqlx.2.sock
worker[1] > mysqld_start:  [' --plugin-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/lib/plugin', '--binlog-format=mixed ']

### safe_path: /data/work/mysql/mysql80-install.bak_asan_ubsan/bin//mysqltest_safe_process --verbose -- /data/work/mysql/mysql80-install.bak_asan_ubsan/bin/mysqld --defaults-group-suffix=.1 --defaults-file=/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/my.cnf --log-output=file --loose-debug-sync-timeout=600 --plugin-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/lib/plugin --binlog-format=mixed --core-file
worker[1] > Started [mysqld.1 - pid: 61921, winpid: 61921]
worker[1] > mysqld_start:  [' --plugin-dir=/data/work/mysql/mysql80-install.bak_asan_ubsan/lib/plugin', '--binlog-format=mixed ']

......

脚本自身支持 debug 参数

如果引用(source)的脚本支持 debug 参数,比如常用的 $rpl_debug,则可以修改相应的 .inc 文件以获得更多的 debug 信息。

perl 的调试模式

添加-d 参数可进入 perl 语言的 debug 模式。示例:

wslu@ubuntu:/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test$ perl -d mysql-test-run.pl --timer  --force --parallel=1 --vardir=var-rpl --suite=rpl

Loading DB routines from perl5db.pl version 1.60
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(mysql-test-run.pl:54):  push @INC, ".";
  DB<1> l
54==>  push @INC, ".";
55
56:  use My::ConfigFactory;
57:  use My::CoreDump;
58:  use My::File::Path;    # Patched version of File::Path
59:  use My::Find;
60:  use My::Options;
61:  use My::Platform;
62:  use My::SafeProcess;
63:  use My::SysInfo;
  DB<1> n
main::(mysql-test-run.pl:72):  require "lib/mtr_gcov.pl";
  DB<1> l
72==>  require "lib/mtr_gcov.pl";
73:  require "lib/mtr_gprof.pl";
74:  require "lib/mtr_io.pl";
75:  require "lib/mtr_lock_order.pl";
76:  require "lib/mtr_misc.pl";
77:  require "lib/mtr_process.pl";
78
79:  our $secondary_engine_support = eval 'use mtr_secondary_engine; 1';
80
81   # Global variable to keep track of completed test cases
  DB<1>

调试模式常用命令:

h       查看帮助文档
c line  运行到指定行
n       运行到下一行
s       跳到函数内部运行
l       查看代码
q       退出

参考

MySQL: The MySQL Test Framework

MySQL: Writing Test Cases

MySQL: mysqltest Language Reference

MySQL: Creating and Executing Unit Tests

mysqltest 语法整理 - 叶落 kiss - 博客园 (cnblogs.com)


欢迎关注我的微信公众号【数据库内核】:分享主流开源数据库和存储引擎相关技术。

标题网址
GitHubhttps://dbkernel.github.io
知乎https://www.zhihu.com/people/dbkernel/posts
思否(SegmentFault)https://segmentfault.com/u/dbkernel
掘金https://juejin.im/user/5e9d3ed251882538083fed1f/posts
优快云https://blog.youkuaiyun.com/dbkernel
博客园(cnblogs)https://www.cnblogs.com/dbkernel
PostgreSQL和PostGIS安装、导入shp或gdb格式数据至数据库、使用QGIS测试上传PstGIS数据库操作和代码 本文详细介绍了postgresql和postgis安装步骤,并且使用postgis测试上传shp和gdb格式的矢量数据至数据库,包括步骤和代码,并使用qgis连接postgis数据查看数据库里的数据,数据依旧和本地数据一样可查看可编辑,方便后续数据底座开发和服务。 阅读详情

相关推荐

比较几款国际主流的电子元器件及物料清单管理软件 – 工具汇总

Arenasolution 老牌的基于云计算物料清单管理软件,bom.com就是他们家的,10天免费试用,功能被分成4个不同的产品, 和传统ERP功能上有重叠,偏向于物流生产规划,一定程度可以取代ERP的生产规划模块,平均价格70美元/月/席位。网页客户端,不支持离线   SiliconExpert 曾经的老牌物料清单管理软件,后被Arrow 收购,14天免费试用,功能被分成4个不同的产品

u012062784的专栏 7237

MySQL日志介绍

0或OFF表示禁用,1或ON表示启用。设置binlog的最大存储上线,当日志达到该日志的上限时,mysql会重新创建一个日志开始记录,不过偶尔也会超出该设置的binlog,一般都是因为即将达到上限时候,产生了一个比较大的事物,为了保证事物的安全,mysql不会将同一个事物分开记录到两个binlog。主要记录MySQL数据库的变化,二进制日志以一种有效的格式,并且是事务安全的方式包含更新日志中可用的所有信息,二进制日志包含了所有更新了数据或者已经潜在更新了数据的语句,语句以“事件”的形式保存,描述数据更改。.

TimeFriends 1418

从零到一:手把手教你用海康VisionMaster完成第一个字符识别项目(附完整流程与避坑点)

本文详细介绍了如何使用海康VisionMaster完成首个字符识别项目,涵盖从环境搭建、图像预处理到系统集成的完整流程。特别分享了Blob分析配置、字符识别优化等实战技巧,帮助开发者避开常见陷阱,快速掌握VisionMaster的基本操作,提升工业自动化场景下的字符识别效率。

weixin_29313423的博客 672

MySQL Query Log

MySQL不像Oracle会在源码中植入大量的调试入口,最近突然要调试一下MySQL的SQL执行过程,于是上官方查了一下,发现只有一个叫做Query Log的机制。当开关被打开之后,所有执行的SQL Statement都会被记录下来,非常详细,基本能够达到调试的目的。这是官方给出的Query Log功能描述: The general query log is a general record...

weixin_30872671的博客 136

Isaac Sim 使用经验(配置要求,云服务器)

Google Colab及AutoDL都是在docker内运行,其中google colab并不支持docker指令,而依照AutoDL的相关文档,AutoDL并不直接提供docker指令。2. Google Colab/AutoDL 不支持图形化界面,图形渲染等任务,所以没有办法使用Omniverse Streaming进行直播,从而更好的对结果进行展示。对于第一点,或许存在直接手动复现镜像的可能,但是考虑到Isaac Sim/Isaac Lab由于比较新,可能不够稳定,因此还是按照官方文档进行部署。

weixin_44211433的博客 4591

网工最容易搞混的三个概念:防火墙、网闸、堡垒机,一文让你轻松搞明白。

网闸的作用可以简单概括为:在两个或多个不同安全级别的网络(如内网和外网、普通网与高安全网、受限网与互联网)之间建立一个严格隔离、信息流转的安全桥梁。它的核心任务是实现数据安全传输与隔离,避免网络之间的直接连接带来的安全隐患。数据传输安全:网闸保证数据从一个网络到另一个网络时,能够进行审查、过滤和转换,防止恶意数据或非法信息被传入内部网络或外部泄露。高安全性隔离:网闸常常用于企业的内外网隔离、军事网络、政府机关等对数据隔离要求极高的环境。

HWP18612324139的博客 3639

MySQL——日志管理(binarylog、querylog)

文章目录一、查询日志二、二进制日志 ***** 一、查询日志 说明: 查询日志记录了数据库客户端所有的语句,二进制日志不包含查询数据的SQL。 参数说明: 3306[youngboy]>select @@general_log; +---------------+ | @@general_log | +---------------+ | 0 | +-------...

hdfeng的博客 607

陀螺仪与加速度计的姿态融合——互补滤波

本篇文章我们来讲讲如何将陀螺仪和加速度计的数据结合起来,获取更准确的姿态数据,使用的是互补滤波的方法。

小白白学电子 2万+

Mysql query log

一、查询日志的概念:   查询日志记录MySQL中所有的query,通过"--log[=file_name]"来打开该功能。由于记录了所有的query,包括所有的select,体积比较大,开启后对性能也有比较大的影响,所以请大家慎用该功能。一般只用于跟踪某些特殊的sql性能问题才会短暂打开该功能。默认的查询日志文件名为:hostname.log.    To enable the general...

weixin_33676492的博客 231

MLNX_OFED 5.4-3.7.5.0 驱动安装:银河麒麟V10SP2 ARM 内核升级后编译避坑 3 步

本文详细介绍了在银河麒麟V10SP2 ARM环境下安装MLNX_OFED 5.4-3.7.5.0驱动的完整流程,包括内核升级后的驱动兼容性挑战、编译环境准备、分步编译与安装流程以及性能优化与故障排查。特别针对国产化ARM服务器(如华为Atlas系列)提供了实用的解决方案和常见问题处理建议,帮助用户顺利完成mlnx网卡驱动的安装与配置。

weixin_29184075的博客 406

TensorRT量化实战教程:从PTQ到QAT,让你的模型推理速度飞起来

无论是PTQ的“快速落地”,还是QAT的“精度极致”,TensorRT量化技术都能成为你模型部署路上的“性能引擎”。通过本教程的实战项目,你已掌握从技术原理到工程落地的全流程能力——现在,不妨将你的模型代入其中,亲眼见证它在速度与精度的双重提升中“焕发生机”。若你在实操中遇到任何卡点,随时可以针对具体问题交流,我会尽全力帮你突破量化部署的每一个瓶颈。

FJN110的博客 239

Laravel 5 SQL语句打印日志

Laravel 5 用DB自带的方式打印SQL语句: DB::enableQueryLog(); DB::getQueryLog(); 得到的结果语句和参数是分开的,非常不利于验证。 [ 0 =&gt; array:3 [▼ "query" =&gt; "select * from `mall_users` where `mall_users`.`id` = ? limit ...

qq_35255775的博客 1293

【图论】系列(七)图论的中心性度量方法及重要性评价指标

图论中的中心性度量方法是用来衡量图中各个节点(或顶点)相对重要性的指标。

qq_30066733的博客 1078

特性介绍 | MySQL 测试框架 MTR 系列教程(一):入门篇

作者:卢文双 资深数据库内核研发 以前对 MySQL 测试框架 MTR 的使用,主要集中于 SQL 正确性验证。近期由于工作需要,深入了解了 MTR 的方方面面,发现 MTR 的能力不仅限于此,还支持单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁等功能,因此,本着分享的精神,将其总结成一个系列。 主要内容如下: 入门篇:机制、编译安装、参数、指令、推荐用法、添加 case、异常调试 进阶篇:高阶用法,包括单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁 源码篇 语法篇

dbkernel 的博客 1095

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

特性介绍 | MySQL 测试框架 MTR 系列教程(二):进阶篇 - 内存/线程/代码覆盖率/单元/压力测试

以前对 MySQL 测试框架 MTR 的使用,主要集中于 SQL 正确性验证。近期由于工作需要,深入了解了 MTR 的方方面面,发现 MTR 的能力不仅限于此,还支持单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁等功能,因此,本着分享的精神,将其总结成一个系列。 主要内容如下: - 入门篇:工作机制、编译安装、参数、指令示例、推荐用法、添加 case、常见问题、异常调试 - 进阶篇:高阶用法,包括单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁 - 源码篇 - 语法篇

dbkernel 的博客 1042

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Cantian connector for MySQL与Cantian存储引擎集成:完整解决方案解析

前往项目官网免费下载:[https://ar.openeuler.org/ar/](https://ar.openeuler.org/ar/?utm_source=csdn_blog) 在当今大数据时代,数据库的高性能、高可用性和可扩展性成为企业级应用的关键需求。**Cantian connector for MySQL**与**Cantian存储引擎**的集成解决方案,为MySQL用户提供了一

gitblog_06880的博客 211

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Salt State 状态系统全解析:SLS 文件、Top File 与模块热加载机制

Salt(SaltStack)提供了一套完整的状态系统接口,用于从中心管理节点集中定义并强制 minion(被管理节点)的配置状态,这一机制即软件配置管理(Software Configuration Management,SCM)的核心实现。本文以 [doc/ref/states/index.rst](https://link.gitcode.com/i/397ae61b35d86dc0ef40

gitblog_06813的博客 172

how to enable MySQL query log?

1、to enable the query log,put this in /etc/my.cnf in the [mysqld] section log=/usr/local/mysql_query.log 2、this worked for me(Mysql 5.6.12 on windows),set parameter int the mysql console: set globa

河南骏的博客 710

laravel查询最后执行的一条sql语句

引用 DB; use Illuminate\Support\Facades\DB; DB::enableQueryLog(); $query = DB::table('test')->orderBy('id', 'desc')->get();//需要执行的SQL语句 print_r(DB::getQueryLog());

Johnston先森的博客 2045

解决Laravle内存泄漏的问题

最近对老项目进行了重构,需要将老版数据库里的数据迁移到新版的数据库,由于新旧两版的数据库表结构存在较大差异,所以写了php脚本来迁移数据。在Laravel项目下的app\Console\Commands目录下创建命令行类,之后在linux命令行执行 php artisan data:v2 运行 迁移代码很简单,只有几行,用到了laravle查询构建器的chunk方法: public function familyUploadCount() { $service = app(DataSe.

竹杖芒鞋轻胜马 1197

Laravel 打印完整的sql语句

用DB自带的getQueryLog方法直接打印: DB::connection()->enableQueryLog(); // 开启QueryLog \App\User::find(1); dump(DB::getQueryLog()); 得到的结果语句与参数是分开的,非常不方便验证 [ 0 => array:3 [▼ "query" => "select * from `mall_users` where `mall_users`.`id` = ? limit 1

Ysy3757的博客 1890
上一篇: 源码分析 | MySQL测试框架 MTR 系列教程(三):源码篇
下一篇: 万字长文 | 业内 MySQL 线程池主流方案详解 - MariaDB/Percona/AliSQL/TXSQL/MySQL企业版
dbkernel
博客等级 码龄4年 60粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值