- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
。
作者:卢文双 资深数据库内核研发 。
序言:
以前对 MySQL 测试框架 MTR 的使用,主要集中于 SQL 正确性验证。近期由于工作需要,深入了解了 MTR 的方方面面,发现 MTR 的能力不仅限于此,还支持单元测试、压力测试、代码覆盖率测试、内存错误检测、线程竞争与死锁等功能,因此,本着分享的精神,将其总结成一个系列.
主要内容如下:
由于个人水平有限,所述难免有错误之处,望雅正.
本文是第二篇进阶篇 .
本文首发于 2023-05-01 21:03:44 。
MTR 系列基于 MySQL 8.0.29 版本(编译情况也在 8.0.32 版本验证过),且主要在 Ubuntu 22.04 X86_64 验证(部分指令也在 Ubuntu 20.04 X86_64、Ubuntu 22.04 ARM64、MacOS M1 做了验证),如有例外,会特别说明.
上一篇文章《MySQL 测试框架 MTR 系列教程(一):入门篇》介绍了 mtr 的原理、目录结构、参数及常见用法,侧重于 最常见的 SQL 正确性验证 ,但 mtr 能做更多的事情,比如 内存错误、线程竞争、代码覆盖率、压力测试等 ,本文主要介绍这些内容,涉及的相关工具如下:
本文将逐一介绍对各个工具的支持情况.
补充:
MariaDB 已经很好的支持了以上工具集:
Compile and Using MariaDB with Sanitizers (ASAN, UBSAN, TSAN, MSAN) - MariaDB Knowledge Base 。
Compiling MariaDB for Debugging - MariaDB Knowledge Base (支持 valgrind) 。
首先说明一下与本文相关的 MySQL 编译选项:
-DCMAKE_BUILD_TYPE=type 。
The type of build to produce
RelWithDebInfo
: default value 。 Enable 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 . -DWITH_DEBUG=bool 。
Whether to include debugging support. The default is OFF . 。
-DWITH_ASAN=bool 。
Whether to enable the AddressSanitizer, for compilers that support it. The default is off . 。
-DWITH_ASAN_SCOPE=bool 。
Whether to enable the AddressSanitizer -fsanitize-address-use-after-scope Clang flag for use-after-scope detection. The default is off . To use this option, -DWITH_ASAN must also be enabled. 。
-DWITH_LSAN=bool 。
Whether to run LeakSanitizer, without AddressSanitizer. The default is OFF . 。
This option was added in MySQL 8.0.16. 。
-DWITH_MSAN=bool 。
Whether to enable MemorySanitizer, for compilers that support it. The default is off . 。
For this option to have an effect if enabled, all libraries linked to MySQL must also have been compiled with the option enabled. 。
-DWITH_TSAN=bool 。
Whether to enable the ThreadSanitizer, for compilers that support it. The default is off . 。
-DWITH_UBSAN=bool 。
Whether to enable the Undefined Behavior Sanitizer, for compilers that support it. The default is off . 。
-DWITH_UNIT_TESTS={ON|OFF} 。
If enabled, compile MySQL with unit tests. The default is ON unless the server is not being compiled. 。
-DWITH_VALGRIND=bool 。
Whether to compile in the Valgrind header files, which exposes the Valgrind API to MySQL code. The default is OFF . 。
To generate a Valgrind-aware debug build, -DWITH_VALGRIND=1 normally is combined with -DWITH_DEBUG=1 . See Building Debug Configurations . 。
-DENABLE_GCOV=bool 。
Whether to include gcov support ( Linux only ). 。
-DENABLE_GPROF=bool 。
Whether to enable gprof ( optimized Linux builds only ). The default is OFF . 。
-DWITH_TEST_TRACE_PLUGIN=bool 。
Whether to build the test protocol trace client plugin (see Using the Test Protocol Trace Plugin ). By default, this option is disabled . Enabling this option has no effect unless the WITH_CLIENT_PROTOCOL_TRACING option is enabled. If MySQL is configured with both options enabled, the libmysqlclient client library is built with the test protocol trace plugin built in, and all the standard MySQL clients load the plugin. However, even when the test plugin is enabled, it has no effect by default. Control over the plugin is afforded using environment variables; see Using the Test Protocol Trace Plugin . 。
Note 。
Do not enable the WITH_TEST_TRACE_PLUGIN option if you want to use your own protocol trace plugins because only one such plugin can be loaded at a time and an error occurs for attempts to load a second one. If you have already built MySQL with the test protocol trace plugin enabled to see how it works, you must rebuild MySQL without it before you can use your own plugins. 。
For information about writing trace plugins, see Writing Protocol Trace Plugins . 。
-DWITH_CLIENT_PROTOCOL_TRACING=bool 。
Whether to build the client-side protocol tracing framework into the client library. By default, this option is enabled . 。
For information about writing protocol trace client plugins, see Writing Protocol Trace Plugins . 。
See also the WITH_TEST_TRACE_PLUGIN option. 。
-DWITH_KEYRING_TEST=bool 。
Whether to build the test program that accompanies the keyring_file plugin. The default is OFF . Test file source code is located in the plugin/keyring/keyring-test directory. 。
-DWITH_NDB_TEST={ON|OFF} 。
If enabled, include a set of NDB API test programs. The default is OFF . 。
详见: MySQL :: MySQL 8.0 Reference Manual :: 2.8.7 MySQL Source-Configuration Options 。
以下是各组件或测试类型的详细介绍.
valgrind 是一个工具集,主要集成了:
mtr 提供的 valgrind 选项如下:
Options for valgrind
callgrind Instruct valgrind to use callgrind.
helgrind Instruct valgrind to use helgrind.
valgrind Run the "mysqltest" and "mysqld" executables using
valgrind with default options.
valgrind-all Synonym for --valgrind.
valgrind-clients Run clients started by .test files with valgrind.
valgrind-mysqld Run the "mysqld" executable with valgrind.
valgrind-mysqltest Run the "mysqltest" and "mysql_client_test" executable
with valgrind.
valgrind-option=ARGS Option to give valgrind, replaces default option(s), can
be specified more then once.
valgrind-options=ARGS Deprecated, use --valgrind-option.
valgrind-path=<EXE> Path to the valgrind executable.
从代码看:
--valgrind
或 --valgrind-mysqltest
选项,才会用到 mysql_client_test
。 编译选项 : -DWITH_DEBUG=1 -DWITH_VALGRIND=1 。
使用建议 :
1、推荐指令可参考 mysql-test/collections/ 目录下的文件 default.daily-valgrind 、 default.push-valgrind 、 default.weekly-valgrind .
2、据我实测, 如需测试 valgrind 所有功能,需在原有指令基础上添加 --valgrind 选项 。比如:
# 官方 collections 中的示例指令:
perl mysql-test-run.pl --timer --force --skip-rpl --comment=all_default_valgrind --vardir=var-all_default_valgrind --skip-ndb
# 添加 --valgrind
perl mysql-test-run.pl --timer --force --skip-rpl --comment=all_default_valgrind --vardir=var-all_default_valgrind --skip-ndb --valgrind
3、在同时启用 ASAN 和 valgrind 的情况下,并在运行 mtr 时添加 --valgrind 选项,mtr 会因 valgrind memcheck 与 asan 冲突而 crash,因此,valgrind 与 asan 不建议同时启用 .
Sanitizers 是谷歌发起的开源工具集,已经成为静态和动态代码分析的利器,可以检查 内存错误、未初始化的读取、线程安全和未定义的行为等 相关的问题.
优点 :与同类型分析工具相比,Sanitizers 带来的性能损失通常要小得多,而且往往提供的信息更详细.
缺点 :代码(可能还有工具链的一部分)需要使用附加的标志重新编译.
Sanitizers 包括如下组件:
AddressSanitizer/ASAN 。
检查内存地址相关问题,包括内存泄漏、释放后使用、重复释放、堆溢出、栈溢出等问题.
通过 编译插桩(CTI) ,能够发现此堆/栈/全局变量读写溢出,内存泄露等问题,并将信息直接打印到日志中.
ASAN 是一个快速的内存错误检测工具。它非常快,只拖慢程序两倍左右(比起 Valgrind 快多了) .
它包括一个编译器 instrumentation 模块和一个提供 malloc()/free() 替代项的运行时库.
LeakSanitizer/LSAN 。
检查内存泄漏问题。它是 集成在 Address Sanitizer 中 的一个相对独立的工具,它工作在检查过程的最后阶段.
UndefinedBehaviorSanitizer/UBSAN 。
检测未定义行为(使用空指针、有符号整数溢出等).
ThreadSanitizer/TSAN 。
检查线程数据竞争和死锁问题.
MemorySanitizer/MSAN 。
检查使用未初始化内存问题.
内核 Sanitizer 包括 KASAN 和 KMSAN 。
Sanitizers 项目本是 LLVM 项目的一部分,但 GNU 也将该系列工具加入到了自家的 GCC 编译器中(clang 当然也支持).
ASAN/AddressSanitizer 能检测很多种内存错误,主要包含如下类别:
-fsanitize-address-use-after-return=(never|runtime|always)
default: runtime
)
ASAN_OPTIONS=detect_stack_use_after_return=1
(already enabled on Linux). ASAN_OPTIONS=detect_stack_use_after_return=0
. -fsanitize-address-use-after-scope
) 更详细的示例 case:参考 https://learn.microsoft.com/zh-cn/cpp/sanitizers/asan-error-examples?view=msvc-170 。
性能影响 :使用 ASAN 后,性能会降低 2 倍.
安装 :有一个单独的动态库 libasan6.so ,会随 gcc 安装.
编译选项 : -DWITH_DEBUG=1 -DWITH_ASAN=1 ,可选择启用 -DWITH_ASAN_SCOPE=1 。
验证版本 :8.0.29 。
MTR 选项 : --sanitize 。
使用建议 :
1、ASAN 功能强大,相较于 valgrind,对性能影响小很多,建议作为主要的内存检测工具 .
2、由于 mtr 需要用到 /usr/bin/perl ,因此,有可能出现 perl 自身某些函数的内存泄漏问题被 Leak Sanitizer 检测到,导致 mtr 测试失败,此时,将问题函数添加到 lsan.supp 文件即可解决。比如 Ubuntu 22.04 perl v5.34.0 会遇到内存泄漏,同样的,Ubuntu 20.04 perl v5.30.0 就无该问题.
# 语法
interceptor_via_fun:NameOfCFunctionToSuppress
interceptor_via_fun:-[ClassName objCMethodToSuppress:]
interceptor_via_lib:NameOfTheLibraryToSuppress
# 示例
interceptor_via_fun:Perl_safesyscalloc
interceptor_via_fun:Perl_safesysmalloc
参考:
# LSAN suppressions for gcc/clang
leak:Perl_safesyscalloc
leak:Perl_safesysmalloc
leak:Perl_safesysrealloc
leak:Perl_savesharedpv
leak:Perl_Slab_Alloc
leak:Perl_newUNOP_AUX
leak:Perl_newSTATEOP
leak:Perl_pmruntime
leak:/usr/bin/perl
leak:/lib64/libperl.so.*
leak:/bin/bash
leak:/usr/bin/zip
# OpenLDAP bug 9081
# Fixed in 2.4.49, we build with 2.4.48
leak:ldap_initialize
# sasl_client_init will load all available plugins with _sasl_load_plugins().
# It seems some of the SASL plugin have leaks.
# Both LSAN and Valgrind report leaks.
leak:sasl_client_add_plugin
该内容来源于源码文件,可见官方知晓 Perl 高版本的内存泄漏问题,以此方式来忽略.
在 Ubuntu 22.04 X86_64 运行:
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --vardir=var-rpl --suite=rpl --sanitize
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --max-test-fail=0 --vardir=var-binlog --suite=binlog --sanitize
LSAN/LeakSanitizer 用于内存泄漏检测.
性能影响 :使用 LSAN 后,除了执行的最后阶段会有一个内存泄漏检测之外,几乎没有性能开销.
安装 :有一个单独的动态库 liblsan0.so ,会随 gcc 安装.
编译选项 : -DWITH_DEBUG=1 -DWITH_LSAN=1 。
验证版本 :8.0.29 。
MTR 选项 : --sanitize 。
使用建议 :
lsan.supp
格式见 「ASAN」小节。 只要编译时启用 ASAN 或 LSAN,在运行时添加 --sanitize 选项即可.
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --max-test-fail=0 --vardir=var-binlog --suite=binlog --sanitize
UBSAN/UndefinedBehaviorSanitizer 是针对未定义行为的检测器,速度很快.
UBSAN 需要在编译时修改程序,以捕获程序执行期间的各种未定义行为。比如:
更多行为详见 :
UndefinedBehaviorSanitizer — Clang 17.0.0git documentation (llvm.org) 。
性能影响 :UBSAN 的运行时成本很小,对地址空间布局或 ABI 没有影响.
安装 :有一个单独的动态库 libubsan1.so ,会随 gcc 安装.
编译选项 : -DWITH_DEBUG=1 -DWITH_UBSAN=1 。
验证版本 :8.0.29 。
MTR 选项 : --sanitize 。
使用建议 :
include/not_ubsan.inc
。目前只有如下 case 会跳过 UBSAN:
./t/innodb_tmp_table_heap_to_disk.test
./t/ssl-big.test
./t/count_distinct3.test
./t/multi_update2.test
./t/ds_mrr-big.test
./suite/gis/t/gis_not_ubsan.test
./suite/binlog_gtid/t/binlog_warning_same_server_id.test
只要编译时启用 UBSAN,在运行时添加 --sanitize 选项即可.
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --max-test-fail=0 --vardir=var-binlog --suite=binlog --sanitize
TSAN/ThreadSanitizer 是用于检测数据竞争和线程死锁的工具.
性能影响 :引入 TSAN 后,会降低 5-15 倍性能,同时,内存占用率会提升 5-10 倍.
安装 :有一个单独的动态库 libtsan0.so ,会随 gcc 安装.
编译选项 : -DWITH_DEBUG=1 -DWITH_TSAN=1 。
验证版本 :8.0.29、8.0.32 。
MTR 选项 : --sanitize 。
使用建议 :
1、 TSAN 与 ASAN 不兼容 (一起使用 cmake 会报错 "No mysys timer support detected" ),但 TSAN 与 UBSAN、VALGRIND 兼容 .
2、 对 TSAN 的支持是实验性的,尚不成熟,不建议使用 .
-- Performing Test HAVE_SANITIZE_SCOPE
-- Performing Test HAVE_SANITIZE_SCOPE - Success
CMake Warning at CMakeLists.txt:1101 (MESSAGE):
Thread sanitizer support is currently experimental.
-- Performing Test C_LD_LLD_RESULT
-- Performing Test C_LD_LLD_RESULT - Failed
-- Performing Test CXX_LD_LLD_RESULT
-- Performing Test CXX_LD_LLD_RESULT - Failed
-- Performing Test C_LD_GOLD_RESULT
-- Performing Test C_LD_GOLD_RESULT - Failed
-- Performing Test CXX_LD_GOLD_RESULT
-- Performing Test CXX_LD_GOLD_RESULT - Failed
-- Local boost dir /data/work/mysql/boost_1_77_0
-- Found /data/work/mysql/boost_1_77_0/boost/version.hpp
-- BOOST_VERSION_NUMBER is #define BOOST_VERSION 107700
-- BOOST_INCLUDE_DIR /data/work/mysql/boost_1_77_0
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Could NOT find Threads (missing: Threads_FOUND)
......
-- Looking for timer_create # 由于 timer_create/timer_settime 函数确实存在,尝试调整过 cmake,后续会报一系列错误,该问题不太好调。
-- Looking for timer_create - not found
-- Looking for timer_settime
-- Looking for timer_settime - not found
-- Looking for kqueue
-- Looking for kqueue - not found
-- Performing Test HAVE_SETNS
-- Performing Test HAVE_SETNS - Failed
-- Looking for EVFILT_TIMER
-- Looking for EVFILT_TIMER - not found
CMake Error at configure.cmake:334 (MESSAGE):
No mysys timer support detected!
Call Stack (most recent call first):
CMakeLists.txt:1487 (INCLUDE)
3、如果某些数据竞争或死锁情况是符合预期的,可以通过 mysql-test/tsan.supp 跳过.
#
# Blacklist for Thread Sanitizer.
# Thread Sanitizer can be enabled with -DWITH_TSAN=1
#
# Suppression syntax is documented here:
# https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions
#
race:innobase
race:client/dump/
deadlock:client/dump/
race:perfschema
race:plugin_vars_free_values
race:log_builtins_filter_run
race:MY_LOCALE_ERRMSGS::destroy
race:get_one_variable_ext
race:mysql_set_character_set_with_default_collation
race:ngs::Scheduler_dynamic::wait_if_idle_then_delete_worker
race:ngs::Socket_events::break_loop
deadlock:find_sys_var_ex
deadlock:Persisted_variables_cache::lock
signal:my_print_stacktrace
只要编译时启用 TSAN,在运行时添加 --sanitize 选项即可.
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --max-test-fail=0 --vardir=var-binlog --suite=binlog --sanitize
测试时,在 install database 阶段,线程之间就会有大量 data race,报错示例如下:
// 报错信息位于 mysql-test/var-main-tsan/log/bootstrap.log
==================
WARNING: ThreadSanitizer: data race (pid=65314)
Read of size 4 at 0x555ae20c13b0 by thread T4:
#0 fil_validate_skip /data/work/mysql/mysql-server/storage/innobase/fil/fil0fil.cc:1953 (mysqld+0x541018e)
#1 fil_aio_wait(unsigned long) /data/work/mysql/mysql-server/storage/innobase/fil/fil0fil.cc:8234 (mysqld+0x54109ca)
#2 io_handler_thread /data/work/mysql/mysql-server/storage/innobase/srv/srv0start.cc:279 (mysqld+0x5143b04)
......
#12 std::thread::_State_impl<std::thread::_Invoker<std::tuple<Detached_thread, void (*)(unsigned long), unsigned long> > >::_M_run() /usr/include/c++/11/bits/std_thread.h:211 (mysqld+0x5159b59)
#13 <null> <null> (libstdc++.so.6+0xdc2b2)
Previous write of size 4 at 0x555ae20c13b0 by thread T3:
#0 fil_validate_skip /data/work/mysql/mysql-server/storage/innobase/fil/fil0fil.cc:1953 (mysqld+0x54101a7)
#1 fil_aio_wait(unsigned long) /data/work/mysql/mysql-server/storage/innobase/fil/fil0fil.cc:8234 (mysqld+0x54109ca)
#2 io_handler_thread /data/work/mysql/mysql-server/storage/innobase/srv/srv0start.cc:279 (mysqld+0x5143b04)
......
#12 std::thread::_State_impl<std::thread::_Invoker<std::tuple<Detached_thread, void (*)(unsigned long), unsigned long> > >::_M_run() /usr/include/c++/11/bits/std_thread.h:211 (mysqld+0x5159b59)
#13 <null> <null> (libstdc++.so.6+0xdc2b2)
Location is global 'fil_validate_skip()::fil_validate_count' of size 4 at 0x555ae20c13b0 (mysqld+0x000007a5c3b0)
Thread T4 (tid=65320, running) created by thread T1 at:
#0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
#1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xdc388)
......
#8 handle_bootstrap /data/work/mysql/mysql-server/sql/bootstrap.cc:327 (mysqld+0x387778f)
#9 pfs_spawn_thread /data/work/mysql/mysql-server/storage/perfschema/pfs.cc:2942 (mysqld+0x56751fb)
Thread T3 (tid=65319, running) created by thread T1 at:
#0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
#1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xdc388)
......
#8 handle_bootstrap /data/work/mysql/mysql-server/sql/bootstrap.cc:327 (mysqld+0x387778f)
#9 pfs_spawn_thread /data/work/mysql/mysql-server/storage/perfschema/pfs.cc:2942 (mysqld+0x56751fb)
SUMMARY: ThreadSanitizer: data race /data/work/mysql/mysql-server/storage/innobase/fil/fil0fil.cc:1953 in fil_validate_skip
==================
......
install database 阶段,类似的报错有 200 多个。虽然可以通过 tsan.supp 文件跳过,但毕竟报错涉及较多函数,若全部跳过,可能会影响对正常情况下数据竞争的判断。因此, 个人暂不建议使用 .
MSAN/MemorySanitizer 用于检测对未初始化内存的读取(uninitialized reads)问题.
性能影响 :引入 MSAN 后,性能会降低 3 倍.
编译选项 : -DWITH_DEBUG=1 -DWITH_MSAN=1 。
验证版本:8.0.29 。
MTR 选项 : --sanitize 。
使用建议 :
CMake Warning at CMakeLists.txt:1080 (MESSAGE):
Memory sanitizer support is currently experimental.
CMake Error at CMakeLists.txt:1107 (MESSAGE):
Cannot use AddressSanitizer and MemorySanitizer together
只要编译时启用 MSAN,在运行时添加 --sanitize 选项即可.
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --max-test-fail=0 --vardir=var-binlog --suite=binlog --sanitize
gcov 用于分析代码覆盖率,gprof 用于分析 gcov 生成的统计数据,二者一般一起使用.
gprof 只支持 linux 操作系统,不支持 MacOS .
官方手册:
Gcov (Using the GNU Compiler Collection (GCC)) 。
gprof(1) - Linux manual page (man7.org) 。
超级方便的 Linux 自带性能分析工具!gprof 介绍、安装、使用及实践 - 知乎 (zhihu.com) 。
编译选项: -DWITH_DEBUG=1 -DENABLE_GCOV=1 -DENABLE_GPROF=1 。
使用建议 :
make install
的安装目录测试,必须在 执行编译的源码目录 测试。
源码根目录/build-debug/mysql-test/mysql-test-run.pl
(本人的编译目录是 build-debug)只是封装了一层对 源码根目录/mysql-test/mysql-test-run.pl
的调用:
[apps@node6 mysql-test]$ pwd
/home/apps/mtr/mysql-oracle/mysql-8.0.26/build-debug/mysql-test
[apps@node6 mysql-test]$ cat mysql-test-run.pl
#!/usr/bin/perl
# Call mtr in out-of-source build
$ENV{MTR_BINDIR} = '/home/apps/mtr/mysql-oracle/mysql-8.0.26/build-debug';
chdir('/home/apps/mtr/mysql-oracle/mysql-8.0.26/mysql-test');
exit(system($^X, '/home/apps/mtr/mysql-oracle/mysql-8.0.26/mysql-test/mysql-test-run.pl', @ARGV) >> 8);
注意:
-big-test
的情况下。 collections/
中没有 gcov 的推荐用法。 mysql-test/README.gcov
文件的最后修改日期是 2006 年,已过时,没有参考价值。 直接在安装目录( make install )执行测试,报错:
wslu@ubuntu:/data/work/mysql/mysql80-install.bak_asan_ubsan_gcov_gprof/mysql-test$ ./mtr --gcov
Logging: ./mtr --gcov
MySQL Version 8.0.29
mysql-test-run: *** ERROR: Coverage test needs the source - please use source dist
在 执行编译的目录 (比如 console-build-debug/mysql-test ) 执行:
wslu@ubuntu:/data/work/mysql/mysql-server/console-build-debug/mysql-test$ ./mtr --gcov -big-test
Logging: /data/work/mysql/mysql-server/mysql-test/mysql-test-run.pl --gcov -big-test
MySQL Version 8.0.29
Checking supported features
- Binaries are debug compiled
Purging gcov information from '/data/work/mysql/mysql-server'...
Using suite(s): 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
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
Checking leftover processes
Removing old var directory
Creating var directory '/data/work/mysql/mysql-server/console-build-debug/mysql-test/var'
Installing system database
Using parallel: 1
==============================================================================
TEST NAME RESULT TIME (ms) COMMENT
------------------------------------------------------------------------------
[ 0%] binlog_gtid.binlog_xa_select_gtid_executed_explicitly_crash [ disabled ] Bug#28588717 Fails both on FreeBSD and other platforms
[ 0%] binlog_nogtid.binlog_gtid_next_xa [ disabled ] BUG#33650776 Failure of XA COMMIT of prepared txn, can result in txn rollback
[ 0%] sys_vars.innodb_log_writer_threads_basic [ disabled ] Bug#32129814 SYS_VARS.INNODB_LOG_WRITER_THREADS_BASIC TIMES OUT SPORADICALLY ON PB2
[ 0%] sysschema.v_wait_classes_global_by_avg_latency [ disabled ] BUG#21550054 Test fails too often.
[ 0%] binlog_gtid.binlog_gtid_mix_ok_packet_all_gtids 'mix' [ pass ] 770
[ 0%] binlog_gtid.binlog_gtid_mix_response_packet 'mix' [ pass ] 6474
[ 0%] binlog_gtid.binlog_xa_trx_gtid_response_packet 'mix' [ pass ] 683
......
[ 0%] binlog_gtid.binlog_gtid_errors 'mix' [ pass ] 1583
......
如果想执行测试后分析 gmon.out ,则可添加 -gprof 参数(仅支持 linux):
wslu@ubuntu:/data/work/mysql/mysql-server/console-build-debug/mysql-test$ ./mtr --gcov -gprof -big-test
那么,在 gcov 执行完成后, mtr 就会自动调用 gprof 解析 gmon.out 文件 .
但在 CentOS 7.6(云服务器 4C8G SSD)实测时遇到问题——gprof 解析 gmon.out 时特别耗时,虽然该进程 CPU 占用率 100%,看起来还在运行,但并无任何输出.
比如,在编译的源码目录中执行:
➜ mysql-test git:(heads/mysql-8.0.26) ✗ ps -axf | grep mysql
30604 ? SN 0:00 \_ perl mysql-test-run.pl --parallel=4 --timer --debug-server --force --testcase-timeout=180 --suite-timeout=1800 --comment=all-default-debug --vardir=var-all-default --skip-combinations --unit-tests-report --no-skip --exclude-platform=windows --skip-ndb --max-test-fail=0 --suite=rpl -gcov -gprof
30611 ? SN 0:30 \_ /usr/bin/perl /home/wslu/work/mysql/mysql-server/mysql-test/mysql-test-run.pl --parallel=4 --timer --debug-server --force --testcase-timeout=180 --suite-timeout=1800 --comment=all-default-debug --vardir=var-all-default --skip-combinations --unit-tests-report --no-skip --exclude-platform=windows --skip-ndb --max-test-fail=0 --suite=rpl -gcov -gprof
32759 ? SN 0:44 \_ /usr/bin/perl /home/wslu/work/mysql/mysql-server/mysql-test/mysql-test-run.pl --parallel=4 --timer --debug-server --force --testcase-timeout=180 --suite-timeout=1800 --comment=all-default-debug --vardir=var-all-default --skip-combinations --unit-tests-report --no-skip --exclude-platform=windows --skip-ndb --max-test-fail=0 --suite=rpl -gcov -gprof
2829 ? SN 0:00 | \_ sh -c gprof /home/wslu/work/mysql/mysql-server/build-debug/runtime_output_directory/mysqld /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gmon.out 2 > /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gprof.err > /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gprof.msg
2830 ? RN 7:07 | \_ gprof /home/wslu/work/mysql/mysql-server/build-debug/runtime_output_directory/mysqld /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gmon.out 2
gmon.out 文件只有 61MB,但 gprof 在解析 gmon.out 时,长达 23 小时无任何输出.
➜ mysql-test git:(heads/mysql-8.0.26) ✗ ls /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gmon.out -lh
-rw-r--r-- 1 wslu wslu 61M Mar 27 20:21 /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gmon.out
➜ mysql-test git:(heads/mysql-8.0.26) ✗ ll /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gprof.err
-rw-r--r-- 1 wslu wslu 0 Mar 28 09:23 /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gprof.err
➜ mysql-test git:(heads/mysql-8.0.26) ✗ ll /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gprof.msg
-rw-r--r-- 1 wslu wslu 0 Mar 28 09:23 /home/wslu/work/mysql/mysql-server/mysql-test/var-all-default/3/mysqld.6/data/gprof.msg
MySQL 使用 TAP (Test Anything Protocol) 和 Google Test Framework 来实现单元测试.
TAP 是 Perl 与测试模块之间所使用的简单的基于文本的接口,主要用于开发 Perl 和 PHP 模块。示例如下:
TAP version 13
ok 1 - testNewArrayIsEmpty(ArrayTest)
ok 2 - testArrayContainsAnElement(ArrayTest)
not ok 3 - Failure: testFailure(FailureErrorTest)
---
message: 'Failed asserting that <integer:2> matches expected value <integer:1>.'
severity: fail
data:
got: 2
expected: 1
...
not ok 4 - Error: testError(FailureErrorTest)
1..4
为了实现 C/C++ 的单元测试,MySQL 开发了一个用于生成 TAP 文本的库 libmytap.a ,源码路径位于 unittest/mytap/ .
Google Test Framework,与 MyTAP 类似,也是一个单元测试框架,但提供了更丰富的功能:
编译选项 : -DWITH_DEBUG=1 -DWITH_UNIT_TESTS={ON|OFF} ,默认是 ON .
执行路径 :必须在编译的源码目录中执行.
使用方法 :
make test
或 make test-unit
指令,虽然按手册描述两个指令都能实现单元测试效果,但实测 make test-unit
会输出更详细的信息,因此, 建议使用 make test-unit
。 编译目录/mysql-test
中执行 mtr 指令时,添加 --unit-tests-report
选项。 注意事项 :
若启用了 ASAN:
make test-unit
,可能会因 ASAN 检测到单元测试代码有内存错误( RUN_ALL_TESTS()
的子函数)而导致 case 失败。 .supp
文件,也无法跳过:
asan.supp
文件添加 interceptor_via_fun:RUN_ALL_TESTS
,无法跳过该错误。 LeakSanitizer
检测到内存泄漏,在 lsan.supp
文件添加 leak:RUN_ALL_TESTS
,无法跳过该错误。
==228225==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x620000098e90 at pc 0x5570c34c26fb bp 0x7ffe1d0d0590 sp 0x7ffe1d0d0580
READ of size 2 at 0x620000098e90 thread T0
#0 0x5570c34c26fa in modify_all_zh_pages /data/work/mysql/mysql-server/strings/ctype-uca.cc:4178
#1 0x5570c34c4d89 in init_weight_level /data/work/mysql/mysql-server/strings/ctype-uca.cc:4287
......
#16 0x5570c36724b8 in testing::UnitTest::Run() /data/work/mysql/mysql-server/extra/googletest/googletest-release-1.11.0/googletest[表情]c/gtest.cc:5438
#17 0x5570c3285445 in RUN_ALL_TESTS() /data/work/mysql/mysql-server/extra/googletest/googletest-release-1.11.0/googletest/include/gtest/gtest.h:2490
#18 0x5570c3284f94 in main /data/work/mysql/mysql-server/unittest/gunit/gunit_test_main.cc:150
#19 0x7f680a423d8f in __libc_start_call_main ../sysdeps/nptl[表情]bc_start_call_main.h:58
#20 0x7f680a423e3f in __libc_start_main_impl ..[表情]u[表情]bc-start.c:392
#21 0x5570c2682f34 in _start (/data/work/mysql/mysql-server/console-build-debug/runtime_output_directory/merge_small_tests-t+0x26a9f34)
综上, 运行单元测试时,不建议同时启用 ASAN .
➜ console-build-debug git:(my_learn_8.0.29) ✗ make test
Running tests...
Test project /Users/wslu/work/mysql/mysql-server-8.0/console-build-debug
Start 1: hp_test1
1/223 Test #1: hp_test1 ................................................... Passed 0.49 sec
Start 2: hp_test2
2/223 Test #2: hp_test2 ................................................... Passed 0.74 sec
Start 3: pfs_instr_class
3/223 Test #3: pfs_instr_class ............................................ Passed 0.54 sec
......
Start 206: routertest_component_rest_metadata_cache
206/223 Test #206: routertest_component_rest_metadata_cache ...................***Failed 13.37 sec
Start 207: routertest_component_rest_mock_server
207/223 Test #207: routertest_component_rest_mock_server ...................... Passed 23.60 sec
Start 208: routertest_component_rest_router
208/223 Test #208: routertest_component_rest_router ........................... Passed 3.87 sec
Start 209: routertest_component_rest_routing
209/223 Test #209: routertest_component_rest_routing ..........................***Failed 145.64 sec
Start 210: routertest_component_rest_connection_pool
210/223 Test #210: routertest_component_rest_connection_pool .................. Passed 5.71 sec
Start 211: routertest_component_router_configuration_errors
211/223 Test #211: routertest_component_router_configuration_errors ........... Passed 5.15 sec
Start 212: routertest_component_routing
212/223 Test #212: routertest_component_routing ...............................***Failed 39.04 sec
Start 213: routertest_component_routing_connection
213/223 Test #213: routertest_component_routing_connection ....................***Failed 117.32 sec
Start 214: routertest_component_routing_strategy
214/223 Test #214: routertest_component_routing_strategy ...................... Passed 83.88 sec
Start 215: routertest_component_sd_notify
215/223 Test #215: routertest_component_sd_notify ............................. Passed 22.63 sec
Start 216: routertest_component_shutdown
216/223 Test #216: routertest_component_shutdown .............................. Passed 4.86 sec
Start 217: routertest_component_state_file
217/223 Test #217: routertest_component_state_file ............................ Passed 22.92 sec
Start 218: routertest_component_user_option
218/223 Test #218: routertest_component_user_option ........................... Passed 0.74 sec
Start 219: routertest_component_metadata_http_auth_backend
219/223 Test #219: routertest_component_metadata_http_auth_backend ............***Failed 76.95 sec
Start 220: routertest_component_socket_close
220/223 Test #220: routertest_component_socket_close .......................... Passed 162.52 sec
Start 221: routertest_component_routing_splicer
221/223 Test #221: routertest_component_routing_splicer ....................... Passed 287.30 sec
Start 222: routertest_component_mock_server
222/223 Test #222: routertest_component_mock_server ........................... Passed 20.44 sec
Start 223: routertest_integration_routing_reuse
223/223 Test #223: routertest_integration_routing_reuse ....................... Passed 440.36 sec
97% tests passed, 6 tests failed out of 223
Total Test time (real) = 2940.80 sec
The following tests FAILED:
14 - merge_small_tests (Failed)
206 - routertest_component_rest_metadata_cache (Failed)
209 - routertest_component_rest_routing (Failed)
212 - routertest_component_routing (Failed)
213 - routertest_component_routing_connection (Failed)
219 - routertest_component_metadata_http_auth_backend (Failed)
Errors while running CTest
Output from these tests are in: /Users/wslu/work/mysql/mysql-server-8.0/console-build-debug/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
make: *** [test] Error 8
wslu@ubuntu:/data/work/mysql/mysql-server/console-build-debug$ head -n 100 /tmp/maketestunit.out
Test project /data/work/mysql/mysql-server/console-build-debug
Start 14: merge_small_tests
Start 15: merge_large_tests
1/223 Test #14: merge_small_tests ..........................................***Failed 70.09 sec
[==========] Running 2386 tests from 132 test suites.
[----------] Global test environment set-up.
[----------] 5 tests from BoundsCheckedArrayDeathTest
[ RUN ] BoundsCheckedArrayDeathTest.BoundsCheckRead
[ OK ] BoundsCheckedArrayDeathTest.BoundsCheckRead (616 ms)
[ RUN ] BoundsCheckedArrayDeathTest.BoundsCheckAssign
[ OK ] BoundsCheckedArrayDeathTest.BoundsCheckAssign (329 ms)
[ RUN ] BoundsCheckedArrayDeathTest.BoundsCheckPopFront
[ OK ] BoundsCheckedArrayDeathTest.BoundsCheckPopFront (276 ms)
[ RUN ] BoundsCheckedArrayDeathTest.BoundsCheckResize
[ OK ] BoundsCheckedArrayDeathTest.BoundsCheckResize (277 ms)
[ RUN ] BoundsCheckedArrayDeathTest.BoundsCheckResizeAssign
[ OK ] BoundsCheckedArrayDeathTest.BoundsCheckResizeAssign (290 ms)
[----------] 5 tests from BoundsCheckedArrayDeathTest (1794 ms total)
[----------] 1 test from DebugDeathTest
[ RUN ] DebugDeathTest.Suicide
[ OK ] DebugDeathTest.Suicide (178 ms)
[----------] 1 test from DebugDeathTest (178 ms total)
......
216/223 Test #1: hp_test1 ................................................... Passed 0.96 sec
Start 12: pfs_misc
217/223 Test #10: pfs_noop ................................................... Passed 0.76 sec
Start 83: basic
218/223 Test #83: basic ...................................................... Passed 0.12 sec
Start 79: skip
219/223 Test #79: skip ....................................................... Passed 0.07 sec
Start 80: todo
220/223 Test #12: pfs_misc ................................................... Passed 0.91 sec
Start 81: skip_all
221/223 Test #80: todo ....................................................... Passed 0.06 sec
Start 82: no_plan
222/223 Test #81: skip_all ................................................... Passed 0.07 sec
223/223 Test #82: no_plan .................................................... Passed 0.03 sec
94% tests passed, 14 tests failed out of 223
Total Test time (real) = 4334.59 sec
The following tests FAILED:
14 - merge_small_tests (Failed)
15 - merge_large_tests (Failed)
56 - gcs_xcom_xcom_cache (Subprocess killed)
57 - gcs_xcom_control_interface (Failed)
65 - merge_temptable_tests-t (Failed)
187 - routertest_component_bootstrap (Subprocess aborted)
189 - routertest_component_bootstrap_clusterset (Subprocess aborted)
191 - routertest_component_bootstrap_tls_endpoint (Subprocess aborted)
192 - routertest_component_clusterset (Subprocess aborted)
197 - routertest_component_gr_notifications (Failed)
205 - routertest_component_rest_api_enable (Subprocess aborted)
213 - routertest_component_routing_connection (Subprocess aborted)
221 - routertest_component_routing_splicer (Timeout)
223 - routertest_integration_routing_reuse (Failed)
Errors while running CTest
在 编译目录/mysql-test 执行如下指令:
perl mysql-test-run.pl --timer --max-test-fail=0 --force --parallel=1 --max-test-fail=0 --vardir=var-binlog --suite=binlog --unit-tests-report
mtr 会首先运行 binlog suite 的所有 case,之后才会运行单元测试.
涉及压力测试的有两部分:
只有两个:
如需要添加新 case,参考对应 suite 已有 case 照猫画虎即可,后续文章会详解介绍语法.
被 mysql-test-run.pl 调用,参数是 --stress .
使用说明位于 mysql-test/README.stress 文件:
The stress script is designed to perform testing of the MySQL server in
a multi-threaded environment.
All functionality regarding stress testing is implemented in the
mysql-stress-test.pl script.
The stress script allows:
- To stress test the mysqltest binary test engine.
- To stress test the regular test suite and any additional test suites
(such as mysql-test-extra-5.0).
- To specify files with lists of tests both for initialization of
stress db and for further testing itself.
- To define the number of threads to be concurrently used in testing.
- To define limitations for the test run. such as the number of tests or
loops for execution or duration of testing, delay between test
executions, and so forth.
- To get a readable log file that can be used for identification of
errors that occur during testing.
There are two ways to run the mysql-stress-test.pl script:
- For most cases, it is enough to use the options below for starting
the stress test from the mysql-test-run wrapper. In this case, the
server is run automatically, all preparation steps are performed,
and after that the stress test is started.
- In advanced case, you can run the mysql-stress-test.pl script directly.
But this requires that you perform some preparation steps and to specify
a bunch of options as well, so this invocation method may be a bit
complicated.
可见,有两种用法:
大部分情况下,通过 mysql-test-run.pl --stress=[option1,option2,...] 运行即可,该脚本实现了准备阶段、压力测试阶段所需的工作.
更高级的用法是直接执行 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 ). 。
其他参数见手册 MySQL: mysql-stress-test.pl — Server Stress Test Program 。
没找到手册说明,据我理解,只要未主动关闭单元测试标记( -DWITH_UNIT_TESTS={ON|OFF} 选项,默认是开启的),就肯定会编译生成 stress suite.
在 Ubuntu 22.04 X86_64 执行测试,成功.
wslu@ubuntu:/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test$ perl mysql-test-run.pl --force --timer --comment=stress --vardir=var-stress --suite=stress --no-skip --max-test-fail=30
Logging: mysql-test-run.pl --force --timer --comment=stress --vardir=var-stress --suite=stress --no-skip --max-test-fail=30
MySQL Version 8.0.29
##############################################################################
# stress
##############################################################################
Checking supported features
- Binaries are debug compiled
Using suite(s): stress
Collecting tests
Removing old var directory
Creating var directory '/data/work/mysql/mysql80-install.bak_asan_ubsan/mysql-test/var-stress'
Installing system database
Using parallel: 1
==============================================================================
TEST NAME RESULT TIME (ms) COMMENT
------------------------------------------------------------------------------
[ 16%] stress.ddl_myisam [ pass ] 88171
[ 33%] stress.ddl_archive [ pass ] 11868
[ 50%] stress.ddl_csv [ pass ] 8007
[ 66%] stress.ddl_innodb [ pass ] 163638
[ 83%] stress.ddl_memory [ pass ] 84721
[100%] shutdown_report [ pass ]
------------------------------------------------------------------------------
The servers were restarted 1 times
The servers were reinitialized 0 times
Spent 356.405 of 423 seconds executing testcases
Completed: All 6 tests were successful.
指令示例:
perl mysql-stress-test.pl
--stress-suite-basedir=/opt/qa/mysql-test-extra-5.0/mysql-test
--stress-basedir=/opt/qa/test
--server-logs-dir=/opt/qa/logs
--test-count=20
--stress-tests-file=innodb-tests.txt
--stress-init-file=innodb-init.txt
--threads=5
--suite=funcs_1
--mysqltest=/opt/mysql/mysql-5.0/client/mysqltest
--server-user=root
--server-database=test
--cleanup
#### 提交代码时执行
perl mysql-test-run.pl --force --timer --comment=stress --vardir=var-stress --suite=stress --no-skip --max-test-fail=30
#### 每天执行
perl mysql-test-run.pl --force --timer --big-test --comment=stress --vardir=var-stress --suite=stress --no-skip
##### 每周执行 basic
# 相较于提交代码时执行的测试指令,多了 --debug-server 选项
perl mysql-test-run.pl --debug-server --force --timer --comment=stress --vardir=var-stress --suite=stress --no-skip
# 相较于上一条多了 --big-test
perl mysql-test-run.pl --debug-server --force --timer --big-test --comment=stress --vardir=var-stress --suite=stress --no-skip
#### 每天执行 valgrind
perl mysql-test-run.pl --force --timer --comment=stress --vardir=var-stress --suite=stress
#### 每周执行 valgrind
# 指定了 --big-test
perl mysql-test-run.pl --force --timer --big-test --testcase-timeout=60 --debug-server --comment=stress-debug-big --vardir=var-stress-debug-big --suite=stress
# 其他
perl mysql-test-run.pl --force --timer --comment=stress --vardir=var-stress --suite=stress --no-skip --max-test-fail=30
perl mysql-test-run.pl --force --timer --comment=innodb-stress --vardir=var-innodb-stress --suite=innodb_stress --no-skip --max-test-fail=30
注意: mysql-test/README.stress 文件的最后修改日期是 2006 年,已过时,没有参考价值.
编译的源码目录/mysql-test
执行 。 编译的源码目录/mysql-test
和 安装目录/mysql-test
都可以执行 。 名称 | 对其支持是否是实验性的 | 编译兼容性(同时启用可编译成功,则为兼容) | mtr 测试结果 | 结论 |
---|---|---|---|---|
ASAN | 否 | 与 UBSAN 、Valgrind 兼容。 | 若与 Valgrind 同时启用(mtr 指定 --valgrind 等选项),执行 mtr 测试时,会导致很多 case 因 valgrind memcheck 报错而失败。比如 binlog_gtid.binlog_gtid_mix_ok_packet_all_gtids |
ASAN 与 Valgrind 不可同时启用,但可与 UBSAN 同时启用。 |
LSAN | 否 | 已集成到 ASAN,未测试。 | 已集成到 ASAN,无需单独启用。 | |
UBSAN | 否 | 与 ASAN、valgrind、TSAN 都兼容。 | 建议与 ASAN 同时启用 。 | |
MSAN | 是 | 与 ASAN 不兼容,若同时启用,编译会报错。 单独启用 MSAN,cmake 失败,报错。 | MySQL 对其的支持是实验性的,暂不建议使用。 | |
TSAN | 是 | 与 ASAN 不兼容,若同时启用,编译会报错。 与 UBSAN、Valgrind 兼容。 | 即使只启用 TSAN,在运行 mtr 时,install database 阶段依然有大片的 data race。 | MySQL 对其的支持是实验性的,暂不建议使用。 |
valgrind | 否 | 与 ASAN 、UBSAN 、TSAN 兼容。 | 单独启用 valgrind,mtr 可正常执行 完全体 valgrind 测试(mtr 指定 --valgrind 选项) ,memcheck 未报错。 与 ASAN 同时启用时,若执行完全体 valgrind 测试,mtr 会因 valgrind memcheck 与 asan 冲突而 crash 。 |
若要使用,不建议与 ASAN 同时启用。 |
gcov/gprof | 否 | 与 ASAN、UBSAN 兼容。 gprof 只支持 linux,不支持 MacOS/Windows。 | 需要在 执行 cmake 的源码目录 测试。 | 建议与 ASAN、UBSAN 一起启用。 |
单元测试 | 否 | 只要是 DEBUG 版本,就会默认启用。 与 ASAN、UBSAN 兼容,其他组件未验证,理论上也应该兼容。 | 需要在 执行 cmake 的源码目录 测试,运行 make test-unit 指令或 ./mtr --unit-tests-report 。 ASAN 会检测到部分测试 case 自身存在内存泄漏,导致当前 case 失败。 |
做单元测试时建议启用 ASAN/UBSAN/LSAN。 |
压力测试 | 否 | 只要编译,就会产生 stress 、 innodb_stress 两个 suite 。 mysql-stress-test.pl 需要自定义 初始化和运行的 SQL 语句,不建议使用。 |
测试成功。 | 正常运行 mtr 全量 suite 或单独运行 stress 、 innodb_stress suites。 |
注意事项:
本部分是个人根据官方 collections ,结合实际情况给出的建议,仅供参考.
在代码开发阶段,统一使用 debug 版本(编译选项 -DWITH_DEBUG=1 )提前发现问题:
default.push
中的指令集。 mysql-trunk-stage.push
(与 mysql-8.0-stage.push
完全相同,是 default.push
的超集)中的指令集。 内核在发布 alpha 版本前,也要用 debug 版本来验证稳定性:
-DWITH_DEBUG=1 -DWITH_UNIT_TESTS={ON|OFF}
,默认是 ON 。 make test
或 make test-unit
指令,虽然按手册描述两个指令都能实现单元测试效果,但实测 make test-unit
会输出更详细的信息,因此, 建议使用 make test-unit
。 --unit-tests-report
选项也有同样效果。 -DWITH_DEBUG=1 -DWITH_ASAN=1 -DUBSAN=1
,可选择启用 -DWITH_ASAN_SCOPE=1
default.daily
的指令基础上,添加 --sanitize
选项。 perl mysql-test-run.pl --timer --max-test-fail=0 --force --comment=var-rpl --vardir=var-rpl --suite=rpl --sanitize
-DWITH_DEBUG=1 -DENABLE_GCOV=1 -DENABLE_GPROF=1
编译的源码目录
执行测试。 ./mtr --gcov --gprof -big-test --force --max-test-fail=0 --comment=gcov-gprof --vardir=var-gcov-gprof --no-skip
gmon.out
,之后,mtr 会自动调用 gprof 解析该文件 。 mysql-stress-test.pl
脚本,但使用该脚本需要自行编写 stress-init、stress-test 文件,因此, 建议直接测试 stress、innodb_stress 这两个 suites 。
perl mysql-test-run.pl --force --timer --big-test --comment=stress --vardir=var-stress --suite=stress,innodb_stress --no-skip
mysql-test/collections/mysql-trunk-tsan.push
。
-DWITH_DEBUG=1 -DWITH_TSAN=1
perl mysql-test-run.pl --timer --debug-server --force --comment=main-tsan --vardir=var-main-tsan --suite=main
如果需要验证 release 版本稳定性(适用于 QA、研发),可参考 default.daily 中的指令集.
推荐:
--valgrind
参数,asan 会与 memcheck 冲突导致 crash,测试终止。 可选:
-DWITH_VALGRIND=1
持续跟踪后续版本改进情况:
llvm 工具集:
linux kernel 工具集:
MySQL:
欢迎关注我的微信公众号【数据库内核】:分享主流开源数据库和存储引擎相关技术.
标题 | 网址 |
---|---|
GitHub | https://dbkernel.github.io |
知乎 | https://www.zhihu.com/people/dbkernel/posts |
思否(SegmentFault) | https://segmentfault.com/u/dbkernel |
掘金 | https://juejin.im/user/5e9d3ed251882538083fed1f/posts |
CSDN | https://blog.csdn.net/dbkernel |
博客园(cnblogs) | https://www.cnblogs.com/dbkernel |
最后此篇关于特性介绍|MySQL测试框架MTR系列教程(二):进阶篇-内存/线程/代码覆盖率/单元/压力测试的文章就讲到这里了,如果你想了解更多关于特性介绍|MySQL测试框架MTR系列教程(二):进阶篇-内存/线程/代码覆盖率/单元/压力测试的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在做一个关于代码学院的教程,我在这里收到一个错误,说“看起来你的函数没有返回‘唉,你没有资格获得信用卡。资本主义就是这样残酷。’”当收入参数为 75 时。”但是该字符串在控制台中返回(由于某种原因
我正在阅读 Go 的官方教程,但很难理解 Channel 和 Buffered Channels 之间的区别。教程的链接是 https://tour.golang.org/concurrency/2和
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
作为 iOS 新手,有大量书籍可以满足学习基础知识的需求。现在,我想转向一些高级阅读,例如 OAuth 和 SQLite 以及动态 API 派生的 TableView 等。您可以推荐任何资源吗? 最佳
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 8 年前。
前言 很多同学都知道,我们常见的CTF赛事除了解题赛之外,还有一种赛制叫AWD赛制。在这种赛制下,我们战队会拿到一个或多个服务器。服务器的连接方式通常是SSH链接,并且可能一个战队可能会同时有
Memcached是一个自由开源的,高性能,分布式内存键值对缓存系统 Memcached 是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象),这些数据可以是数据库调用、A
Perl 又名实用报表提取语言, 是 Practical Extraction and Report Language 的缩写 Perl 是由 拉里·沃尔(Larry Wall)于19
WSDL 是 Web Services Description Language 的缩写,翻译成中文就是网络服务描述语言 WSDL 是一门基于 XML 的语言,用于描述 Web Services 以
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 6年前关闭。 Improve thi
我正在寻找解释在 WPF 中创建自定义用户控件的教程。 我想要一个控件,它结合了一个文本 block 、一个文本框和一个启动通用文件打开对话框的按钮。我已经完成了布局,一切都连接好了。它有效,但它是三
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我接近 fourth page of the Django tutorial 的开始看着vote查看,最后是这样的: # Always return an HttpResponseRedirect a
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
是否有任何好的 Qt QSS 教程,或者在某个地方我可以看到样式小部件的示例?如果某处可用,我想要一些完整的引用。除了有关如何设置按钮或某些选项卡样式的小教程外,我找不到任何其他内容。 最佳答案 Qt
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!