作者:盧文雙 資深資料庫核心研發
序言:
以前對 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 編譯選項:
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.Whether to include debugging support. The default isOFF
.
Whether to enable the AddressSanitizer, for compilers that support it. The default is off.
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.
Whether to run LeakSanitizer, without AddressSanitizer. The default isOFF
.
This option was added in MySQL 8.0.16.
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.
Whether to enable the ThreadSanitizer, for compilers that support it. The default is off.
Whether to enable the Undefined Behavior Sanitizer, for compilers that support it. The default is off.
If enabled, compile MySQL with unit tests. The default is ON unless the server is not being compiled.
Whether to compile in the Valgrind header files, which exposes the Valgrind API to MySQL code. The default isOFF
.
To generate a Valgrind-aware debug build, -DWITH_VALGRIND=1 normally is combined with -DWITH_DEBUG=1. See Building Debug Configurations.
Whether to include gcov
support (Linux only).
Whether to enable gprof
(optimized Linux builds only). The default isOFF
.
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.
Whether to build the test program that accompanies the keyring_file
plugin. The default isOFF
. Test file source code is located in the plugin/keyring/keyring-test
directory.
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 |