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

去年年底通过微信公众号【数据库内核】设定了一个指标——2023 年要写一系列 个性介绍+内核解析 的文章(现阶段还是以 MySQL 为主)。
尽管关注者很少,但本着“说到就要做到”的准则,从这篇就开始了。

序言:

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

次要内容如下:

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

因为集体程度无限,所述不免有谬误之处,望雅正。

本文是第一篇入门篇

本文首发于 2023-03-18 21:58:52

本系列基于 MySQL 8.0.29 版本,且次要在 Ubuntu 22.04 X86_64 验证(局部指令也在 Ubuntu 20.04 X86_64、Ubuntu 22.04 ARM64、MacOS M1 做了验证),如有例外,会特地阐明。

简介

在批改内核代码后,不仅须要测试新增性能,同时也要对原有性能做回归测试,以保障新加代码对原有性能没有影响,这就须要用到 MySQL 源码自带的测试框架 mtr。

MySQL 测试框架是一个以 MySQL 框架和外部引擎为测试对象的工具,次要执行脚本在装置门路(make install后的门路)下的mysql-test目录,根本笼罩了所有 MySQL 的个性和异常情况。

MySQL 测试框架 mtr 次要蕴含如下几个组件:

  • mysql-test-run.pl :perl 脚本,简称 mtr,是 MySQL 最罕用的测试工具,负责管制流程,包含启停、辨认执行哪些用例、创立文件夹、收集后果等等,次要作用是验证 SQL 语句在各种场景下是否返回正确的后果。
  • mysqltest :C++二进制程序,负责执行测试用例,包含读文件、解析特定语法、执行用例。

    • 用例的非凡语法(比方,--source--replace_column等)都在command_namesenum_commands两个枚举构造体中。
  • mysql_client_test :C++二进制程序,用于测试 MySQL 客户端 API(mysqltest 无奈用于测试 API)。

    • 从代码看,只有启用--valgrind--valgrind-mysqltest 选项,才会用到 mysql_client_test
  • mysql-stress-test.pl :perl 脚本,用于 MySQL Server 的压力测试。
  • 反对 gcov/gprof 代码覆盖率测试工具。

除此之外,还提供了单元测试工具(严格来说不属于 mtr ),以便为存储引擎和插件创立独自的单元测试程序。

因为 MySQL 测试框架的入口是 mysql-test-run.pl(它会调用上述其余组件),因而,个别将 MySQL 测试框架简称为 mtr

mtr 工作原理

概述

mtr 采纳t/r模式(t目录中存储具体的测试 case,文件以.test结尾;r目录中存储了对应 case 的冀望后果,文件以.result结尾),次要测试步骤是“通过执行一个 case,将该 case 的输入后果,与规范的输入后果(冀望后果)作 diff”:

  • 如果齐全一样,则阐明该 case 通过;
  • 反之,则阐明该 case 失败。

    • 可能起因:case 自身写的有问题;MySQL 服务有问题。

如果t目录中的某个 case 在r目录中没有对应.result文件:

  • 那么,只有该 case 能失常执行完,mtr 就会断定该 case 通过;
  • 反之,若执行过程中呈现 mysql server crash 等异样问题,mtr 就会断定该 case 失败。

上文说的 case 是指一系列的语句,包含 SQL 语句和一些必要的 mysqltest command。

所有 case 可分为三局部,别离为:

  • main:测试 case 位于 mysql-test/t 目录,冀望后果(如果有的话)位于mysql-test/r 目录,二者中的文件是一一对应的,比方:mysql-test/t/alter_debug.testmysql-test/r/alter_debug.result
  • suite :门路位于mysql-test/suite 目录,其中蕴含很多测试 case 的汇合,每个汇合都是一个独自的子目录(比方 mysql-test/suite/binlog),在子目录中又别离蕴含 r、t 两个目录。
  • extra :应该是对上述两种 case 的补充,位于mysql-test/extra/ 目录,在 8.0.29 版本中只蕴含binlog_testsrpl_tests 两个汇合。

框架流程

mysql-test-run.pl框架运行流程如下:

1、初始化(Initialization)

  • 确定用例执行范畴,包含运行哪些 suite,skip 哪些用例,在本阶段依据disabled.def文件、--skip-xxx命令(比方skip-rpl)等确定执行用例。
  • 同时,初始化数据库。前面运行用例启动数据库时,不须要每次初始化,只需从这里的目录中拷贝启动。

2、运行用例(run test)

主线程依据参数--parallel(默认是 1)启动一个或者多个用例执行线程(worker),各线程有本人独立的 client port,data dir 等。

启动的 worker 与主线程之间是 server-client 模式,主线程是 server,worker 是 client。

  • 主线程与 worker 是一问一答模式,主线程向 worker 发送运行用例的文件门路、配置文件参数等各种参数信息,worker 向主线程返回运行后果,直到所有在 collection 中的用例都运行结束,主线程 close 各 worker,进行收尾工作。
  • 主线程先读取各 worker 返回值,对上一个用例进行收尾工作。之后,读取 collection 中的用例,通过本地 socket 发送到 worker 线程,worker 线程接管到主线程命令,运行本次用例测试的外围逻辑,次要包含 3 件事:启动 mysqld、启动并监控 mysqltest,解决执行后果

    • 启动 mysqld依据参数启动一个或者多个 mysqld server 过程,大多数状况下会拷贝主线程初始化后的目录到 worker 的数据目录,作为新实例的启动目录,用 shell 命令启动数据库。
    • 启动并监控 mysqltest:用例在 mysqltest 中执行,worker 线程会监控 mysqltest 的运行状态,监测其是否运行超时或者运行完结。
    • 解决执行后果:mysqltest 执行完结会留下执行日志,框架依据执行日志判断执行是否通过,如果没通过是否须要重试等。

rpl.rpl_multi_source_basic 测试 case 为例来阐明执行过程。

# This is the basic test required in for multisource replication# The aim of this file is to test the basic usecases of msr.# 0. Create two masters and a slave and setup a multisource replication#    between them.# 1. create a different databases on each master and test if they are replicated#    to the slave.# 2. create a different table on each master and test if they are replicated to#    the to the slave.# 3. Create a table with the same name on both masters and update non conflicting#    data on that table. Test if the replication is done properly.# 4. Check if updates happen on different master such that the resulting#    data on slave is conflicting, check that one of the channels the slave#    SQL thread is stopped.### Note: Out of convention, server 2 is always made a slave for multisource testing.

启动测试指令 perl mysql-test-run.pl --do-test=rpl_multi_source 后,会启动 3 个 mysqld 过程,其中 2 个 master 节点,1 个 slave 节点:

➜  rpl ps -xf | grep mysql   6982 pts/2    S+     0:00      \_ perl mysql-test-run.pl rpl_multi_source_basic   7125 pts/2    S+     0:00          \_ perl mysql-test-run.pl rpl_multi_source_basic   7130 pts/2    S+     0:00              \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.1 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file   7131 pts/2    Sl     0:04              |   \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.1 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file   7132 pts/2    S+     0:00              \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.2 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file   7133 pts/2    Sl     0:06              |   \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.2 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file   7134 pts/2    S+     0:00              \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.3 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file   7135 pts/2    Sl     0:04              |   \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqld --defaults-group-suffix=.3 --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --log-output=file --loose-debug-sync-timeout=600 --binlog-format=mixed --core-file   7283 pts/2    S+     0:00              \_ /data/work/mysql/mysql80-install.bak_valgrind/bin//mysqltest_safe_process -- /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqltest --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --silent --tmpdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/tmp --character-sets-dir=/data/work/mysql/mysql80-install.bak_valgrind/share/charsets --logdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log --database=test --plugin_dir=/data/work/mysql/mysql80-install.bak_valgrind/lib/plugin --timer-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log/timer --test-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/t/rpl_multi_source_basic.test --tail-lines=20 --result-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/r/rpl_multi_source_basic.result   7284 pts/2    R      0:00                  \_ /data/work/mysql/mysql80-install.bak_valgrind/bin/mysqltest --defaults-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/my.cnf --silent --tmpdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/tmp --character-sets-dir=/data/work/mysql/mysql80-install.bak_valgrind/share/charsets --logdir=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log --database=test --plugin_dir=/data/work/mysql/mysql80-install.bak_valgrind/lib/plugin --timer-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/var/log/timer --test-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/t/rpl_multi_source_basic.test --tail-lines=20 --result-file=/data/work/mysql/mysql80-install.bak_valgrind/mysql-test/suite/rpl/r/rpl_multi_source_basic.result

可见:

  1. 无论是 mysqldtest 还是 mysqld,都是由 mysqltest_safe_process 程序启动的。
  2. --defaults-group-suffix=.1 到 3 别离对应 3 个 mysqld 过程,阐明 mtr 不是靠 mock 的模式来测试的,而是启动真 mysqld 过程来测试

编译装置

装置依赖

mysql-server 编译须要:

# for mysql 8.0sudo apt install gdb gcc g++ cmake -ysudo apt install openssl libssl-dev -ysudo apt install libncurses-dev libudev-dev -ysudo apt install bison flex libaio-dev libreadline-dev libjemalloc-dev -ysudo apt install libevent-dev zlib1g-dev libmecab-dev libgcrypt20-dev -ysudo apt install libsasl2-dev libldap2-dev libtirpc-devsudo apt-get install libsasl2-dev # SASLsudo apt-get install slapd ldap-utils # LDAPsudo apt install valgrind doxygen libcurl4-gnutls-dev -y # extra# centos 7.6sudo yum install cmake gcc g++ # 因为 cmake、gcc 版本偏低,须要自行通过源码编译装置sudo yum install readline-devel bison flex libarchive openssl-develsudo yum install rpcgen libudev-devel ncurses-devel libtirpc libtirpc-develsudo yum install cyrus-sasl-devel # SASLsudo yum install openldap openldap-devel # LDAPsudo yum install valgrind # extra# centos stream 9sudo yum install cmake gcc g++ gcc-toolset-12-gcc gcc-toolset-12-gcc-c++ gcc-toolset-12-binutilssudo yum install readline-devel bison flex libarchive openssl-devel # libtirpc-develsudo yum install rpcgen libudev-devel ncurses-devel libtirpc libtirpc-develsudo yum install cyrus-sasl-devel # SASLsudo yum install openldap openldap-devel # LDAPsudo yum install valgrind # extra# macosbrew install lz4brew install zlibbrew install clang
因为零碎及版本差别,这里列举的软件包可能会有所缺失,版本也可能会有所不同。

对于 mtr 来说,也须要额定装置一些依赖:

# centosyum -y install perl -ysudo yum install perl-JSON -ysudo yum install perl-Test-use-ok.noarch -y# ubuntusudo apt install perl -ysudo perl -MCPAN -e 'install JSON'

编译

Debug 版本编译选项示例:

# for MacOS and UbuntuCURDIR=`pwd`INSTALLDIR=$CURDIR/../../mysql80-installDATADIR=$CURDIR/../../mysql80-default-dataBOOSTDIR=$CURDIR/../../boost_1_77_0rm CMakeCache.txt -fcmake .. \-DCMAKE_BUILD_TYPE=Debug \-DCMAKE_INSTALL_PREFIX=$INSTALLDIR \-DSYSCONFDIR=/etc \-DMYSQL_DATADIR=$DATADIR \-DMYSQL_UNIX_ADDR=/tmp/mysqld.sock \-DMYSQL_TCP_PORT=3306 \-DWITH_MYISAM_STORAGE_ENGINE=1 \-DWITH_INNOBASE_STORAGE_ENGINE=1 \-DENABLED_LOCAL_INFILE=1 \-DWITH_DEBUG=1 \ # 必须是 debug 版本-DWITH_BOOST=$BOOSTDIR \-DWITH_SSL=/usr/local/openssl-1.1.1 \-DFORCE_INSOURCE_BUILD=1# -DWITH_ASAN=ON -DWITH_ASAN_SCOPE=ON -DWITH_UBSAN=ON \ # 抉择启用哪些组件# -DWITH_VALGRIND=ON \# -DENABLE_GCOV=1 -DENABLE_GPROF=1 \if [ $? != 0 ]; then  exit 1fi# for MacOS, only need makemake -j4make install

Release 版本编译选项示例:

#!/bin/bash# for MacOS and UbuntuCURDIR=`pwd`# for 8.0.29INSTALLDIR=$CURDIR/../../mysql80-install#INSTALLDIR=/usrDATADIR=$CURDIR/../../mysql80-default-dataBOOSTDIR=$CURDIR/../../boost_1_77_0rm CMakeCache.txt -fcmake .. \-DCMAKE_BUILD_TYPE=Release \-DBUILD_CONFIG=mysql_release \-DFEATURE_SET=community \-DWITH_EMBEDDED_SERVER=OFF \-DWITHOUT_ROCKSDB=ON \-DWITH_UNIT_TESTS=OFF \-DWITH_BOOST=$BOOSTDIR \-DFORCE_INSOURCE_BUILD=1 \-DCOMPILATION_COMMENT="MySQL build $(date +%Y%m%d.%H%M%S.$(git rev-parse --short HEAD))"#-DCMAKE_INSTALL_PREFIX=$INSTALLDIR \#-DSYSCONFDIR=/etc \#-DMYSQL_DATADIR=$DATADIR \#-DWITH_MYISAM_STORAGE_ENGINE=1 \#-DWITH_INNOBASE_STORAGE_ENGINE=1 \#-DWITH_MEMORY_STORAGE_ENGINE=1 \#-DWITH_PARTITION_STORAGE_ENGINE=1 \if [ $? != 0 ]; then        exit 1fi# for MacOS, only need makemake -j4make install

-DCMAKE_BUILD_TYPE=type 选项阐明:

The type of build to produce:

  • RelWithDebInfo: default valueEnable optimizations and generate debugging information. This is the default MySQL build type.
  • Release: Enable optimizations but omit debugging information to reduce the build size. This build type was added in MySQL 8.0.13 (MySQL 5.7 is not supported).
  • Debug: Disable optimizations and generate debugging information. This build type is also used if the WITH_DEBUG option is enabled. That is, -DWITH_DEBUG=1 has the same effect as -DCMAKE_BUILD_TYPE=Debug.

目录构造

编译装置后,mysql-test 目录树结构如下:

mysql-test├── README├── README.gcov # 代码覆盖率测试阐明,最初更新于2006年├── README.stress # 压力测试阐明,针对 mysql-stress-test.pl ,最初更新于2006年├── collections # 该目录下的文件是官网举荐的回归测试指令集│   ├── README # 阐明文档│   ├── coverage.ignore # 指定须要疏忽代码覆盖率测试的目录│   ├── disabled.def # 列出须要长期禁用的测试用例,在运行测试时会跳过│   ├── disabled-asan.list # 除 disabled.def 文件所列用例之外,还须要长期禁用的测试用例│   ├── disabled-ubsan.list # 同上│   ├── disabled-valgrind.list # 同上│   ├── disabled_ndb.def # 仅在运行 MySQL Cluster 时才须要长期禁用的测试用例        # 适宜每天都运行的回归测试指令集        # 涵盖 default suites、非 default suites、针对复制和binlog的扩大测试(辨别不同的复制参数)、InnoDB 扩大测试(辨别不同页面大小)│   ├── default.daily        # 因为 valgrind 运行比拟耗时,因而,该指令集只能涵盖除 big-test 之外的所有 suites 。        # 须要编译时增加选项 -DWITH_DEBUG=1 -DWITH_VALGRIND=1 的状况下,能力执行 valgrind 测试。        # 留神:通过实测、剖析代码,运行 mtr 时必须增加 --valgrind 选项能力用到 valgrind 组件。│   ├── default.daily-valgrind        # 适宜每周运行一次的指令集,运行耗时能达到48小时。        # 是 default.daily 的超集,同时,还指定了 --debug-server 。        # 笼罩 default suites + 非 default suites + 复制和binlog的扩大 + InnoDB扩大 + 其余按周运行的指令集。│   ├── default.weekly│   ├── default.weekly-ndbcluster # 笼罩 default.daily + ndbcluster + 局部非默认指令集│   ├── default.weekly-protocol # 编译时须要设置 DWITH_TEST_TRACE_PLUGIN=1,只笼罩 main suite。        # 在启用 --big-test 和 --debug-server 选项的前提下,运行所有的指令集。        # 须要编译时增加选项 -DWITH_DEBUG=1 -DWITH_VALGRIND=1 的状况下,能力执行 valgrind 测试。        # 留神:通过实测、剖析代码,运行 mtr 时必须增加 --valgrind 选项能力用到 valgrind 组件。│   ├── default.weekly-valgrind│   ├── default.weekly.basic # 在禁用 --big-test 选项的前提下,运行所有的指令集,即蕴含 default suites + 非 default suites。        # 实用于每次push代码时运行的指令集,能管制在一个小时内。        # 更实用于 mysql 5.7 版本。│   ├── default.push│   ├── default.push-ndbcluster # 分为 default suites + 与 ndbcluster 相干的指令集│   ├── default.push-valgrind # 分为 default suites(排除 rpl)+ ndb 相干 suites + group_replication suite│   ├── mysql-8.0-stage.push # 在 default.push 根底上,为 mysql-8.0-stage 扩大的测试用例,在merge到main分支前应用│   ├── mysql-8.0-stage.push.basic # mysql-8.0-stage.push 的子集│   ├── mysql-trunk-meb-itch.push # 文件为空        # default.push 的超集,目标是在 push 到 main 分支前,提前发现问题。│   ├── mysql-trunk-stage.push # 内容与 mysql-8.0-stage.push 一样,在merge到main分支前应用│   ├── mysql-trunk-stage.push.basic # mysql-trunk-stage.push 的子集│   └── mysql-trunk-tsan.push # 因为 ThreadSanitizer 十分慢,因而,只测试 main suite├── extra # 不属于 main 和 其余 suites 的测试 case│   ├── binlog_tests│   │   ├── binlog.test│   │   ├── binlog_cache_stat.test│   │   ├── binlog_crash_safe_ddl.inc│   │   ├── binlog_ddl.inc        ......│   │   └── tmp_table.test│   └── rpl_tests│       ├── binlog_transaction_compression.inc│       ├── check_slave_delay.inc        ......│       └── type_conversions.test├── lib # 测试框架相干依赖文件,外面次要是一些用perl实现的逻辑。│   ├── My│   │   ├── Config.pm│   │   ├── ConfigFactory.pm        ......│   │   └── Test.pm│   ├── mtr_cases.pm    ......├── lock_order_dependencies.txt # mysql-test-run.pl 读取该文件来管制加锁程序,与 --lock-order 选项无关。该文件非空。# 在 mtr 运行对应工具期间,比方 asan,对应的 .supp 文件用于指定须要跳过的测试用例。## ASAN、LSAN、TSAN 出自谷歌的 Sanitizer 我的项目,蕴含了 ASAN、LSAN、MSAN、TSAN等内存、线程谬误的检测工具。├── asan.supp # ASAN(Address-Sanitizier),内存谬误检测工具。晚期是LLVM中的个性,后被退出GCC 4.8。├── lsan.supp # LSAN(LeakSanitizer),内存透露检测工具,已集成在 ASAN(AddressSanitizer)中。├── tsan.supp # TSAN(ThreadSanitizer),线程间数据竞争的检测工具。├── valgrind.supp # Valgrind 是一个工具集。集成了:                  # Memcheck 内存谬误检测器。                  # Cachegrind 缓存和分支预测分析器。                  # Callgrind 可生成缓存分析器的调用图。                  # Helgrind 线程谬误检测器。                  # DRD 也是线程谬误检测器。                  # Massif 堆分析器,它能够帮忙程序应用更少的内存。                  # DHAT 一种不同类型的堆分析器。应用它能够理解块寿命,块利用率和布局效率低下的问题。├── mtr -> ./mysql-test-run.pl # mysql-test-run.pl 脚本别名├── mysql-stress-test.pl├── mysql-test-run -> ./mysql-test-run.pl├── mysql-test-run.dox├── mysql-test-run.pl # mtr 入口文件,测试框架外围逻辑# include/ 目录蕴含.inc 文件,在测试用例中通过 source 命令引入,就像 C/C++ 的头文件。倡议将多次重复应用的测试语句整合到 .inc 文件中。├── include # include 下所有 *.inc 都会被 t/ 目录下的 *.test 援用│   ├── Load_data.inc    ......│   ├── json_lookup.inc│   ├── keyring_tests│   │   ├── binlog│   │   │   ├── rpl_binlog_cache_encryption.inc        ......│   ├── keyring_udf_keyring_plugin_loaded.inc    ......│   └── year-engine.test# t/ 和 r/ 目录别离对应于 main suite 的测试 case 和 冀望后果。# 测试 case 以 .test 后缀结尾。# 另外还有 .opt 后缀文件,它外面指定了MySQL的参数。某些测试用例会波及重启,在重启时可能会变更 mysql 参数,可能会用 .opt 文件中指定的参数。├── t # 该目录下的每个 *.test 都对应一个测试 case 。│   ├── 1st.test│   ├── admin_interface.test    ......├── r # 门路和命名 与 t/ 目录一一对应,示意对应测试用例的冀望输入。│   ├── 1st.result│   ├── admin_interface.result    ......│   └── year-myisam.result├── std_data # 测试所用的数据文件,某些测试 case 须要应用到。│   ├── 14897.frm│   ├── 256kb.json│   ├── 41_decimal.frm│   ├── 57import.zip    ......│   └── x_y_data.csv# 测试框架有 suite 的概念,每个 suite 为一个测试用例汇合,默认的 suite 为 main,它的测试汇合位于当前目录下的 t/ 目录。# 除了 main suite 之外,其余的 suite 根本都以子目录的模式寄存于以后文件夹,比方 json、binlog 等。├── suite # 本目录下每个子目录都蕴含 include/r/t 三个子目录,其中:          # include/*.inc 会被 t/*.test 援用          # t/*.test 是各个测试case的主文件          # r/*.result 是冀望的测试输入          # 另外,t/ 与 r/ 门路中的文件是一一对应的。│   ├── audit_null    ......│   ├── innodb│   │   ├── include│   │   │   ├── alter_table_pk_no_sort.inc            ......│   │   ├── r│   │   │   ├── add_foreign_key.result│   │   │   ├── alter_crash.result            ......│   │   └── t│   │       ├── add_foreign_key.test│   │       ├── alter_crash.test            ......│   │       └── zlob_update_purge.test│   ├── innodb_fts    ......└── var # 测试开启后 mtr 创立的目录,用于寄存测试过程产生的数据目录、日志等。    ├── data    │   ├── #ib_16384_0.dblwr        ......    ......    ├── my.cnf    ├── run    ├── std_data    │   ├── 14897.frm    ......    └── tmp        └── mysqld.1

参数

参考:

  • MySQL: MySQL Test Programs
  • MySQL: mysql-test-run.pl — Run MySQL Test Suite

罕用参数

  • --force

    • 默认状况下,只有遇到一个 case 出错,测试程序就会退出。
    • 退出该参数后,mtr 会疏忽谬误并继续执行下一个 case 直到所有 case 执行完结再退出。
    • 但如果脚本存在太多谬误还是会退出,可设置--max-test-fail=0 疏忽计数。
  • --max-test-fail

    • 测试过程中失败 case 数达到肯定值会退出,默认值是 10,设置为 0 则会疏忽计数。
  • --record

    • 是否记录 results 后果,首次执行倡议带上,让其主动生成 .results 文件,再基于该文件批改成咱们预期的后果
    • 若一个执行输入后果和 testname.result 文件不同,会生成一个 testname.reject 文件,该文件在下次执行胜利之后被删除;
    • 查看.reject文件的内容,如果外面是冀望的输入,则将内容拷贝到 .result 文件中,作为当前判断运行后果是否通过的根据;
  • --parallel

    • 指定运行测试 case 的并行线程数。
  • —-nowarnings

    • 疏忽 warnings 谬误。
    • 设置该参数后,当呈现 warnings 谬误,不再累加 --max-test-fail
  • --big-test

    • 执行标记为 big 的 test cases,也就是同时笼罩 非 big + big。这是因为标记为 big 的 case 较大、耗时较长,默认不会执行。
  • --only-big-test :只启用带 big 标记的 test cases,也就是会跳过一般的非 big 标记的 cases。
  • --suite=[suitename1,...]

    • 默认状况下 mtr 会执行所有测试 case,但有时候咱们要执行一个测试集,就可用该参数来指定,比方./mtr --suite=rpl 只执行 rpl 测试集。
  • --do-test=events

    • 执行所有以 events为前缀的 case(搜寻范畴为 t/和所有的 suite)。
    • --do-test 的参数反对正则表达式,上述命令等效于 ./mtr --do-test=events.*
    • 所以如果想测试所有的包含 innodb 的 case,能够用 ./mtr --do-test=.*innodb.*
  • 连贯近程的数据库进行 mtr 执行:
# --extern  个别状况下mtr是启动本人的MySQL服务来进行测试,如果在启动时指定参数 --extern,则能够应用指定的 MySQL 服务进行测试./mtr --extern host=192.168.6.1 --extern port=3306 --extern user=root --extern password='123456'  --record --force example.1./mtr --extern host=127.0.0.1 --extern port=3306 --extern user=root --extern password= --force --max-test-fail=0 --suite=main./mtr --extern host=127.0.0.1 --extern port=3306 --extern user=root --extern password= --force --max-test-fail=0 --fast --suite=main
  • --debug-server :Use debug version of server, but without turning on tracing.
  • --platform--exclude-platform :用于指定或排除平台的选项。

    • 如果 MTR 不是运行在 pushbuild test 环境中(存在环境变量PB2WORKDIR,即export PB2WORKDIR=),这两个选项是不失效的。
  • comment=STR :增加该选项后,mtr 会将正文信息打印到 stdout 。比方 --comment=all-default-big
############################################################################### all-default-big##############################################################################
  • --vardir=DIR :指定测试过程中生成的文件寄存的目录,默认是以后门路下的var/
  • --report-features :指定该选项后,mtr 首先运行名为 report_features 的 case,该 case 没有任何输入(设置了--disable_query_log) 。
  • --unit-tests-report :加上该参数后,如果在编译后的源码目录执行 mtr,会在测试的最初阶段加上每个测试用例的报告信息。
......[----------] 1027 tests from Spec/ReuseConnectionTest (404 ms total)[----------] Global test environment tear-down[==========] 1027 tests from 1 test suite ran. (70804 ms total)Total Test time (real) = 3363.87 sec......The following tests FAILED:        203 - routertest_component_metadata_ttl (Subprocess aborted)        206 - routertest_component_rest_api_enable (Failed)        222 - routertest_component_routing_splicer (Failed)        224 - routertest_integration_routing_reuse (Failed)Errors while running CTest  [  FAILED  ] CheckEdgeHttpsPortValues/UseEdgeHttpsPortValues.ensure_bootstrap_works_for_edge_https_port_values/1, where GetParam() = 65535 (1444 ms)  [  FAILED  ] 1 test, listed below:  [  FAILED  ] CheckEdgeHttpsPortValues/UseEdgeHttpsPortValues.ensure_bootstrap_works_for_edge_https_port_values/1, where GetParam() = 65535   1 FAILED TEST  [  FAILED  ] Spec/SplicerFailParamTest.fails/client_ssl_dh_params_not_exists, where GetParam() = 64-byte object <C8-CE 3D-2F 4D-56 00-00 F0-DA BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 3D-D1 F9-2E 4D-56 00-00 AD-D0 F9-2E 4D-56 00-00> (383 ms)  [  FAILED  ] 1 test, listed below:  [  FAILED  ] Spec/SplicerFailParamTest.fails/client_ssl_dh_params_not_exists, where GetParam() = 64-byte object <C8-CE 3D-2F 4D-56 00-00 F0-DA BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 B0-DB BB-30 4D-56 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 3D-D1 F9-2E 4D-56 00-00 AD-D0 F9-2E 4D-56 00-00>   1 FAILED TEST  [  FAILED  ] 0 tests, listed below:   0 FAILED TESTS  [  FAILED  ] Spec/ReuseConnectionTest: SetUpTestSuite or TearDownTestSuite   1 FAILED TEST SUITEUnit tests: 98% tests passed, 4 tests failed out of 224  The following tests FAILED:        206 - routertest_component_rest_api_enable (Failed)        222 - routertest_component_routing_splicer (Failed)        224 - routertest_integration_routing_reuse (Failed)Report from unit tests in /data/work/mysql/mysql-server/mysql-test/var-all-default-big/ctest.log------------------------------------------------------------------------------The servers were restarted 3 timesThe servers were reinitialized 0 timesSpent 53.181 of 3579 seconds executing testcasesCompleted: Failed 1/6 tests, 83.33% were successful.Failing test(s): unit_tests
  • --no-skip :指定该选项后,即便 .inc 文件中要求的条件不满足,也会运行所有的 mtr 测试 cases 。特地地,在 include/excludenoskip.list 文件中指定的 .inc 文件列表仍然会跳过。
  • --skip-ndb :与选项--skip-ndbcluster 含意雷同,示意跳过与 ndb 相干的 suites,默认启用。

    • ndb 引擎也是开源的(storage/ndb/),波及 ndb 引擎的 suites 包含:
- ndb- ndb_big- ndb_opt- ndb_ddl- ndb_binlog- ndb_rpl- rpl_ndb- ndbcluster- gcol_ndb- json_ndb
  • --with-ndb-only :与选项--with-ndbcluster-only 含意雷同,只运行与 ndb 相干的 suites 。如果没显示指定--suites 参数,则会跳过所有非 ndb 的 suites ;反之,若指定了,也会额定运行指定的 suites 。
  • --ps-protocol :在 client 和 server 端之间应用 prepared-statement 协定(binary),会将--ps-protocol 参数间接传给 mysqltest 程序。
  • --skip-combinations :疏忽组合文件或选项,也就是疏忽:
# 启动 mtr 时的日志:Collecting tests - Adding combinations for binlog - Adding combinations for binlog_gtid - Adding combinations for binlog_nogtid - Adding combinations for rpl - Adding combinations for rpl_gtid - Adding combinations for rpl_nogtid# 对应于./suite/rpl_nogtid/combinations./suite/binlog_gtid/combinations./suite/binlog/combinations./suite/rpl/combinations./suite/rpl_gtid/combinations./suite/binlog_nogtid/combinations# 除此之外,还有:./suite/ndb_rpl/t/ndb_rpl_innodb2ndb.combinations./suite/ndb_rpl/t/ndb_rpl_conflict_epoch.combinations./suite/ndb_rpl/t/ndb_rpl_basic.combinations

suitename 可选范畴

main,audit_null,auth_sec,binlog,binlog_gtid,binlog_nogtid,clone,collations,component_keyring_file,connection_control,encryption,engines,engines/funcs,engines/iuds,engines/rr_trx,federated,funcs_1, # 额定性能(包含视图、存储过程、INFORMATION_SCHEMA等)funcs_2, # 额定性能(字符集等)gcol, # 虚构生成列gis,group_replication,information_schema,innodb,innodb_fts, # 全文索引innodb_gis,innodb_stress,innodb_undo,innodb_zip,interactive_utilities,jp, # 日语字符集json,large_tests,lock_order,max_parts,memcached,network_namespace,opt_trace,parts,parts/special_tests,perfschema,query_rewrite_plugins,rpl,rpl_gtid,rpl_nogtid,secondary_engine,service_status_var_registration,service_sys_var_registration,service_udf_registration,special,stress,sys_vars,sysschema,test_service_sql_api,test_services,x

suites 分类

default suites:

auth_sec,binlog,binlog_gtid,binlog_nogtid,clone,collations,component_keyring_file,connection_control,encryption,federated,funcs_2,gcol,gis,information_schema,innodb,innodb_fts,innodb_gis,innodb_undo,innodb_zip,interactive_utilities,json,main,opt_trace,parts,perfschema,query_rewrite_plugins,rpl,rpl_gtid,rpl_nogtid,secondary_engine,service_status_var_registration,service_sys_var_registration,service_udf_registration,sys_vars,sysschema,test_service_sql_api,test_services,x

非 default suites:

funcs_2, stress, jp, nistengines, memcached, audit_nullgroup_replication

指令示例

mtr 执行门路:

  • 代码覆盖率、单元测试只能在 编译的源码目录/mysql-test 执行。
  • 其余测试在 编译的源码目录/mysql-test装置目录/mysql-test 都能够执行。
  • 如无非凡需要,更倡议在装置目录执行 mtr 测试(目录构造更清晰)。

罕用指令:

  • 在未编写 .result文件的状况下,可先通过--reocrd选项生成.result文件,再基于该文件批改成冀望的后果:
perl mysql-test-run.pl --record mytest
  • 常态下执行,不加 --reocrd选项,这样才会比对理论后果与冀望后果是否雷同:
perl mysql-test-run.pl mytestcase1perl mysql-test-run.pl --suites=main,rpl # 指定多个 suites
  • 当一些测试 case 频繁失败时,可独自运行这些 case 以便调试:
./mtr testcasename --record# 只运行根底套餐里的 subquery_all 用例( t/subquery_all.test )# 可选 --charset-for-testdb=utf8mb4./mtr --force --big-test --nowarnings --max-test-fail=0 main.subquery_all# 如需执行多个 case,可通过空格宰割,比方:./mtr --force --big-test --nowarnings --max-test-fail=0 main.subquery_all main.myisam_explain_json_non_select_none
  • 如果不指定任何 suite,mtr 默认会执行所有 default suites(包含 main)
./mtr --force
  • 执行 main suite 中的所有 case(所有mysql-test/t/*.test),疏忽两头的 warnings 报错,强制运行完所有 case:
./mtr  --suite=main --force --max-test-fail=0 --nowarnings --parallel=8./mtr  --suite=main --force --max-test-fail=0 --nowarnings --parallel=8 --big-test
  • 执行所有以 events 为前缀的 case,搜寻范畴为 mysql-test/tmysql-test/suite,留神不包含extra/
# --do-test 参数反对正则表达式,该指令等效于./mtr --do-test=events.*./mtr --do-test=events --force --max-test-fail=0# 如果想测试所有蕴含 innodb 的 case,能够用 ./mtr --do-test=.*innodb.*

非凡用法:

  • 1、筹备数据库: create database test

    • a)执行 ./mtr --extern host=127.0.0.1 --extern port=3306 --extern user=root --extern password= --force --max-test-fail=0 --suite=main ,第一个非 skipped case 能够执行胜利,但之后的 case 全副失败。
    • b)剖析起因,发现是每执行完一个 case ,mtr 就会 shutdown mysqld server,下一个 case 再启动,而这里是应用的内部 mysql,则不会启动。
  • 2、查看手册,发现有一个参数能够管制是否每个 case 都重启 mysqld:
--fastDo not perform controlled shutdown when servers need to be restarted or at the end of the test run. This is equivalent to using --shutdown-timeout=0.
  • 3、增加后,尽管不重启了,但会导致一些 case 失败。 这是因为有些 case 须要初始化一些参数
Note    If a test case has an .opt file that requires the server to be restarted with specific options, the    file will not be used. The test case likely will fail as a result.

可见,官网对这种用法的反对尚不欠缺

举荐用法

如果须要验证 release 版本稳定性(实用于 QA、研发),可参考 default.daily 中的指令集。

  • 该指令集笼罩了单元测试(必须以 DEBUG 编译)、压力测试等。

如何增加测试用例?

1. 示例一

咱们通过一个最简略的例子来阐明这个框架是怎么应用的。

1.1. 创立测试用例

mysql-test/t 目录下创立一个文件名为 mytest.test 的测试用例:

--disable_warningsDROP TABLE IF EXISTS t1;SET @@sql_mode='NO_ENGINE_SUBSTITUTION';--enable_warningsSET SQL_WARNINGS=1;--echo #--echo # test content--echo #CREATE TABLE t1 (a INT);INSERT INTO t1 VALUES (1);INSERT INTO t1 VALUES (2);SELECT * FROM t1;DROP TABLE t1;

mysql-test/r 目录下创立名为mytest.result 的文件:

DROP TABLE IF EXISTS t1;SET @@sql_mode='NO_ENGINE_SUBSTITUTION';SET SQL_WARNINGS=1;## test content#CREATE TABLE t1 (a INT);INSERT INTO t1 VALUES (1);INSERT INTO t1 VALUES (2);SELECT * FROM t1;a12DROP TABLE t1;

可见,.result 文件中不仅要记录 SQL,还要记录输入后果。

1.2. 执行测试,胜利

指令:

cd mysql80-debug/mysql-test./mtr main.mytest

输入:

Logging: ./mtr  main.mytestMySQL Version 8.0.29Checking supported features - Binaries are debug compiledUsing 'all' suitesCollecting testsChecking leftover processesRemoving old var directoryCreating var directory '/Users/wslu/work/mysql/mysql80-debug/mysql-test/var'Installing system databaseUsing parallel: 1==============================================================================                  TEST NAME                       RESULT  TIME (ms) COMMENT------------------------------------------------------------------------------[ 50%] main.mytest                               [ pass ]     63[100%] shutdown_report                           [ pass ]------------------------------------------------------------------------------The servers were restarted 0 timesThe servers were reinitialized 0 timesSpent 0.063 of 16 seconds executing testcasesCompleted: All 2 tests were successful.

看到 successful 阐明执行胜利。

1.3. 批改 result 文件

mytest.result 文件中增加一些字符:

DROP TABLE IF EXISTS t1;SET @@sql_mode='NO_ENGINE_SUBSTITUTION';SET SQL_WARNINGS=1;## test content#CREATE TABLE t1 (a INT);INSERT INTO t1 VALUES (1);INSERT INTO t1 VALUES (2);SELECT * FROM t1; # new commenta12DROP TABLE t1;

1.4. 再次执行测试,失败

再次执行指令./mtr main.mytest ,可见# new comment 那一行报错:

==============================================================================                  TEST NAME                       RESULT  TIME (ms) COMMENT------------------------------------------------------------------------------[ 50%] main.mytest                               [ fail ]        Test ended at 2023-03-20 15:07:50CURRENT_TEST: main.mytest--- /Users/wslu/work/mysql/mysql80-debug.bak_asan_ubsan_gcov/mysql-test/r/mytest.result  2023-03-20 10:07:31.000000000 +0300+++ /Users/wslu/work/mysql/mysql80-debug.bak_asan_ubsan_gcov/mysql-test/var/log/mytest.reject  2023-03-20 10:07:50.000000000 +0300@@ -7,7 +7,7 @@ CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2);-SELECT * FROM t1; # new comment+SELECT * FROM t1; a 1 2mysqltest: Result length mismatchThe result from queries just before the failure was:DROP TABLE IF EXISTS t1;SET @@sql_mode='NO_ENGINE_SUBSTITUTION';SET SQL_WARNINGS=1;## test content#CREATE TABLE t1 (a INT);INSERT INTO t1 VALUES (1);INSERT INTO t1 VALUES (2);SELECT * FROM t1;a12DROP TABLE t1;safe_process[19130]: Child process: 19131, exit: 1 - the logfile can be found in '/Users/wslu/work/mysql/mysql80-debug.bak_asan_ubsan_gcov/mysql-test/var/log/main.mytest/mytest.log'[100%] shutdown_report                           [ pass ]------------------------------------------------------------------------------

mtr 会指出具体是哪行导致的 case 失败。

常见问题 FAQ

test case failed 起因

  1. 产生的测试后果文件与预期输入文件 diff 后果不统一:

    1. 冀望输出的 SQL 执行胜利,理论执行失败。
    2. 冀望输出的 SQL 执行失败,理论执行胜利。
    3. 比方:mysql-test/t/select_all.test 这个测试 case,其预期后果在mysql-test/r/select_all.result,在理论执行时,会将执行后果与mysql-test/r/select_all.result作比拟,若不统一,则失败,并在mysql-test/var/log目录生成一个.reject文件。
  2. 测试过程中 mysql server 挂掉。这种状况个别会报“失落连贯”的谬误。
  3. 测试期间 MySQL Server 端写入了未过滤的 warnings 或 errors 日志。
此外,测试用例能够执行内部程序,因而在某些方面,测试框架能够扩大为测试 SQL 语句以外的用处。
最初,能够在测试中嵌入一小段 Perl 代码。这有时可用于执行超出测试语言或 SQL 能力的操作或执行逻辑。

可应用一些技巧来定为具体的谬误起因,详见下节。

异样调试

剖析日志

默认状况下,在目录 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 --verboseLogging: mysql-test-run.pl  --timer --force --parallel=1 --vardir=var-rpl --suite=rpl --verbose> exe_name: mysqldMySQL Version 8.0.29Checking supported features - Binaries are debug compiled> Testing FIPS: --test-ssl-fips-mode 0 error:0F06D065:common libcrypto routines:FIPS_mode_set:fips mode not supportedUsing suite(s): rplCollecting 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_rplRemoving 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-rplInstalling 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.sqlUsing parallel: 1==============================================================================                  TEST NAME                       RESULT  TIME (ms) COMMENT------------------------------------------------------------------------------> Client connectedworker[1] > mtr_ping_port: 13000worker[1] > FREEworker[1] > mtr_ping_port: 13001worker[1] > FREEworker[1] > mtr_ping_port: 13002worker[1] > FREEworker[1] > mtr_ping_port: 13003worker[1] > FREE......worker[1] > mtr_ping_port: 13029worker[1] > FREEworker[1] > Using MTR_BUILD_THREAD 300, with reserved ports 13000..13029worker[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 SPORADICALLYworker[1] > Running test: rpl.rpl_plugin_loadworker[1] > Setting timezone: GMT-3worker[1] > Cleaning datadirs...worker[1] > clean_dir: /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmpworker[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 = 13000worker[1] > MASTER_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqld.1.sockworker[1] > MASTER_X_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqlx.1.sockworker[1] > SLAVE_MYPORT = 13002worker[1] > SLAVE_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqld.2.sockworker[1] > SLAVE_X_MYSOCK = /data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-rpl/tmp/mysqlx.2.sockworker[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-fileworker[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 参数和 gdb 参数

mtr 反对的一些 debug 参数:

  debug                 Dump trace output for all servers and client programs.  debug-common          Same as debug, but sets 'd' debug flags to                        "query,info,error,enter,exit"; you need this if you                        want both to see debug printouts and to use                        DBUG_EXECUTE_IF.  debug-server          Use debug version of server, but without turning on                        tracing.  debugger=NAME         Start mysqld in the selected debugger.  gdb                   Start the mysqld(s) in gdb.  lldb                  Start the mysqld(s) in lldb.

可见,要想跟踪调用过程,只有 --debug--gdb 参数满足要求,会生成 trace 信息。

示例:

# 这几条指令很消耗内存./mtr --debug --suite=rpl./mtr --gdb --suite=rpl./mtr --debug --gdb --suite=rpl

指令执行后,生成 trace 文件,比方 var/log/bootstrap.trace

脚本本身反对 debug 参数

如果援用(source)的脚本反对 debug 参数,比方罕用的 $rpl_debug,则能够批改相应的 .inc 文件以取得更多的 debug 信息。

perl 的调试模式

增加-d 参数可进入 perl 语言的 debug 模式,便于调试 mysql-test-run.pl 及其调用。示例:

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=rplLoading DB routines from perl5db.pl version 1.60Editor 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> l54==>  push @INC, ".";5556:  use My::ConfigFactory;57:  use My::CoreDump;58:  use My::File::Path;    # Patched version of File::Path59:  use My::Find;60:  use My::Options;61:  use My::Platform;62:  use My::SafeProcess;63:  use My::SysInfo;  DB<1> nmain::(mysql-test-run.pl:72):  require "lib/mtr_gcov.pl";  DB<1> l72==>  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";7879:  our $secondary_engine_support = eval 'use mtr_secondary_engine; 1';8081   # Global variable to keep track of completed test cases  DB<1>

调试模式常用命令:

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

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

题目网址
GitHubhttps://dbkernel.github.io
知乎https://www.zhihu.com/people/dbkernel/posts
思否(SegmentFault)https://segmentfault.com/u/dbkernel
掘金https://juejin.im/user/5e9d3ed251882538083fed1f/posts
CSDNhttps://blog.csdn.net/dbkernel
博客园(cnblogs)https://www.cnblogs.com/dbkernel