TokuDB に関するテストが mariadb-10.4.18 で FAIL する件

Vagrant Box bento/ubuntu-20.04 で Building MariaDB on Ubuntu に従い MariaDB をビルドした(※)ところ、TokuDB に関連するテストが FAIL した。なお MariaDB のバージョンは mariadb-10.4.18 である。ここに解決方法を記しておく。

※ ただし、記事中の 10.3 をすべて 10.4 に置き換えて手順を実行した。


テストの実行結果から重要そうな部分のみ抜粋する。... は省略を表す。

> ./mysql-test/mtr --suite=tokudb --force

...

==============================================================================

TEST                                      RESULT   TIME (ms) or COMMENT
--------------------------------------------------------------------------

worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019
tokudb.bf_create_select                  [ skipped ]  Test needs --big-test
tokudb.bf_create_select_hash_part        [ skipped ]  Test needs --big-test

...

tokudb.type_temporal_upgrade             [ disabled ]
tokudb.type_timestamp_explicit           [ disabled ]
worker[1] mysql-test-run: WARNING: Process [mysqld.1 - pid: 393963, winpid: 393963, exit: 512] died after mysql-test-run waited 0.2 seconds for /home/vagrant/repo/mariadb-server/build/mysql-test/var/run/mysqld.1.pid to be created.
tokudb.type_varchar                      [ fail ]
        Test ended at 2021-04-13 12:46:49

CURRENT_TEST: tokudb.type_varchar


Failed to start mysqld.1
mysqltest failed but provided no output


 - saving '/home/vagrant/repo/mariadb-server/build/mysql-test/var/log/tokudb.type_varchar/' to '/home/vagrant/repo/mariadb-server/build/mysql-test/var/log/tokudb.type_varchar/'
***Warnings generated in error logs during shutdown after running tests: tokudb.type_varchar

2021-04-13 12:46:48 0 [ERROR] Couldn't load plugins from 'ha_tokudb.so'.
2021-04-13 12:46:48 0 [ERROR] /home/vagrant/repo/mariadb-server/build/sql/mysqld: unknown option '--tokudb'
2021-04-13 12:46:48 0 [ERROR] Aborting

...

Errors/warnings were found in logfiles during server shutdown after running the
following sequence(s) of tests:
    tokudb.type_varchar
    tokudb.ext_key_1_innodb
    tokudb.ext_key_2_innodb
    tokudb.simple_join_tokudb_innodb
    tokudb.truncate_txn_rollback_innodb
    tokudb.type_bit_innodb
    tokudb.bug-1657908
    tokudb.gap_lock_error
    tokudb.dir-per-db-with-custom-data-dir
19 tests were skipped, 0 by the test itself.

mysql-test-run: *** ERROR: there were failing test cases

Couldn't load plugins from 'ha_tokudb.so'. と言われているので、ha_tokudb.so を探してみる。どうやらビルド自体はされていそうだ。

> pwd
/home/vagrant/repo/mariadb-server/build

> ag -g ha_tokudb
storage/tokudb/CMakeFiles/tokudb.dir/ha_tokudb.cc.o
storage/tokudb/ha_tokudb.so

よくわからないので、それっぽい issue がないか MariaDB の JIRA を漁ってみる。MDEV-16183 TokuDB tests fail on Fedora 28 がそれっぽい。

LD_PRELOAD を設定しろと書いてあるので、やってみると…通った!何故これで上手く行くのかは、上の issue に書かれているのでそちらを読んでほしい。

> LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ./mysql-test/mtr --suite=tokudb

...

==============================================================================

TEST                                  WORKER RESULT   TIME (ms) or COMMENT
--------------------------------------------------------------------------

worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019
tokudb.bf_create_select                  [ skipped ]  Test needs --big-test
tokudb.bf_create_select_hash_part        [ skipped ]  Test needs --big-test

...

tokudb.hotindex-del-fast                 w3 [ pass ]  61017
tokudb.hotindex-update-0                 w5 [ pass ]  57358
--------------------------------------------------------------------------
The servers were restarted 9 times
Spent 714.488 of 119 seconds executing testcases

Completed: All 214 tests were successful.

27 tests were skipped, 7 by the test itself.

追記: MariaDB10.4 branch の HEAD (c03841ec0e2b7ac11711243d29821038b26e3edf) において、suite やテストを指定せずに mysql-test-run.pl を実行すると、途中で mysqld が死んでエラーになるという問題があったのだが、それも TokuDB が原因のようである。次のいずれかの方法で回避できる。

> LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ./mysql-test/mtr
> ./mysql-test/mtr --skip-test=tokudb    # TokuDB 関連のテストをスキップ

Building MySQL 8.0.23 on Ubuntu 20.04

Vagrant Box bento/ubuntu-20.04MySQL 8.0.23 をビルドした記録。

> cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"

何はともあれソースコードを入手する。最初は GitHub から取ろうとしたのだが、MySQL の boost のバージョン指定が厳しく、面倒だったので boost 同梱版のソースを公式からダウンロードした。

wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.23.tar.gz
tar xfv mysql-boost-8.0.23.tar.gz
cd mysql-8.0.23/

MySQL Internals Manual の 4.3 Quick How-to-Build Instructions に従って進めていく。yoku さんの ConoHaの上でひたすらMySQLをビルドする簡単なおしごと in 2019年 も参考にした。

何はともあれ cmake がないと始まらないので、それだけ入れてビルドしてみる。

sudo apt-get install cmake
mkdir bld && cd $_
cmake -DWITH_BOOST=../boost ..
# cmake -DWITH_BOOST=../boost .. -DCMAKE_BUILD_TYPE=Debug

「XX がない」と言われるので、XX をインストールして再度 cmake -DWITH_BOOST=../boost ..。cmake が通るまでこれを繰り返す。煩雑になるので過程は省略するが、最終的に↓を実行すれば通るようになる。

sudo apt-get install g++ pkg-config

cmake が通ったことを確認してビルドを実行。MySQL のビルドは時間がかかる。

make -j4

問題なくビルドできたはずだ。以下では、試行錯誤の最中に発見した些細なバグについて解説する。ビルドの方法だけ知りたい場合は読む必要はない。


正しくビルドできていることを確認する意味で、テストを実行してみる。

 ./mysql-test/mtr --parallel=4

最初はいい感じに動くのだが、テストが依存しているライブラリやコマンドが足りず、一部のテストが落ちる。それらをインストールしてから再実行。

 sudo apt-get install libjson-perl unzip zip
 ./mysql-test/mtr --parallel=4

しかし、main.cast がまだ通らない。次の diff で落ちているようだ。なお、テストの完全な出力は記事末尾に載せた。

 SELECT CAST(TIME'08:09:10' AS YEAR);
 CAST(TIME'08:09:10' AS YEAR)
-2020
+2021
 SELECT CAST(TIME'00:00:00' AS YEAR);
 CAST(TIME'00:00:00' AS YEAR)
-2020
+2021

公式ドキュメント によれば、

For a TIME value, return the current year.

とのことなので、SELECT CAST(TIME'08:09:10' AS YEAR); が2021年現在において、2021 を返すのは正しい振る舞いと考えられる。よって、これはテストがおかしい。一応、それらしきバグレポも上がっている。

MySQL(のテスト)のバグで、すべてのテストを完走させることはできなかったが、ビルド自体は正しくできていると思ってよさそうだ。


vagrant@vagrant:~/mysql-8.0.23/bld
> ./mysql-test/mtr main.cast --retry=0
Logging: /home/vagrant/mysql-8.0.23/mysql-test/mysql-test-run.pl  main.cast --retry=0
MySQL Version 8.0.23
Checking supported features
Using 'all' suites
Collecting tests
Checking leftover processes
Removing old var directory
Creating var directory '/home/vagrant/mysql-8.0.23/bld/mysql-test/var'
Installing system database
Using parallel: 1

==============================================================================
                  TEST NAME                       RESULT  TIME (ms) COMMENT
------------------------------------------------------------------------------
[ 50%] main.cast                                 [ fail ]
        Test ended at 2021-01-23 01:40:47

CURRENT_TEST: main.cast
--- /home/vagrant/mysql-8.0.23/mysql-test/r/cast.result 2020-12-11 10:42:20.000000000 +0300
+++ /home/vagrant/mysql-8.0.23/bld/mysql-test/var/log/cast.reject       2021-01-23 04:40:47.304244731 +0300
@@ -1760,10 +1760,10 @@
 2010
 SELECT CAST(TIME'08:09:10' AS YEAR);
 CAST(TIME'08:09:10' AS YEAR)
-2020
+2021
 SELECT CAST(TIME'00:00:00' AS YEAR);
 CAST(TIME'00:00:00' AS YEAR)
-2020
+2021
 SELECT CAST(ST_PointFromText('POINT(10 10)') AS YEAR);
 ERROR HY000: Incorrect arguments to cast_as_year
 CREATE TABLE t AS SELECT CAST("2010" AS YEAR);

mysqltest: Result content mismatch


The result from queries just before the failure was:
TIMESTAMPADD(MINUTE, 1, CAST(1988 AS YEAR))
NULL
Warnings:
Warning 1292    Incorrect datetime value: '1988'
SELECT CAST(CAST(1988 AS YEAR) AS SIGNED);
CAST(CAST(1988 AS YEAR) AS SIGNED)
1988
SELECT CAST(CAST(1988 AS YEAR) AS UNSIGNED);
CAST(CAST(1988 AS YEAR) AS UNSIGNED)
1988
SELECT CAST(TIMESTAMP'579-10-10 10:10:10' AS YEAR);
CAST(TIMESTAMP'579-10-10 10:10:10' AS YEAR)
NULL
Warnings:
Warning 1292    Truncated incorrect YEAR value: '579'
SELECT CAST(STR_TO_DATE('nope','%d-%m-%Y') AS YEAR);
CAST(STR_TO_DATE('nope','%d-%m-%Y') AS YEAR)
NULL
Warnings:
Warning 1411    Incorrect datetime value: 'nope' for function str_to_date
safe_process[1263073]: Child process: 1263074, exit: 1

 - the logfile can be found in '/home/vagrant/mysql-8.0.23/bld/mysql-test/var/log/main.cast/cast.log'

[100%] shutdown_report                           [ pass ]
------------------------------------------------------------------------------
The servers were restarted 0 times
The servers were reinitialized 0 times
Spent 0.000 of 5 seconds executing testcases

Completed: Failed 1/2 tests, 50.00% were successful.

Failing test(s): main.cast

The log files in var/log may give you some hint of what went wrong.

If you want to report this error, please read first the documentation
at http://dev.mysql.com/doc/mysql/en/mysql-test-suite.html

mysql-test-run: *** ERROR: there were failing test cases