GA

2025/12/07

今年もConoHaのVPSでMySQLをビルドする 2025年

この記事は ConoHa - Qiita Advent Calendar 2025 の7番目の窓です。

昨日は 8mitsu さんの ConoHaをMCPで操作してみた でした。

この記事は MySQL - Qiita Advent Calendar 2025 の7番目の窓でもあります。

こちらは昨日は @taka_yuki_04 さんの MySQL キーリングプラグインからコンポーネントへの移行 でした。


今年はビルドのために 6コア6GBのOracle Linux 10を起動しました。去年までは1コア2GBで頑張っていましたがそれで最近のMySQLをビルドしていると一晩かかるのでもうつらい。


OSはOracle Linuxの10にしてみた。


$ cat /etc/os-release

NAME="Oracle Linux Server"

VERSION="10.1"

ID="ol"

ID_LIKE="fedora"

VARIANT="Server"

VARIANT_ID="server"

VERSION_ID="10.1"

PLATFORM_ID="platform:el10"

PRETTY_NAME="Oracle Linux Server 10.1"

ANSI_COLOR="0;31"

CPE_NAME="cpe:/o:oracle:linux:10:1:server"

HOME_URL="https://linux.oracle.com/"

BUG_REPORT_URL="https://github.com/oracle/oracle-linux"

ORACLE_BUGZILLA_PRODUCT="Oracle Linux 10"

ORACLE_BUGZILLA_PRODUCT_VERSION=10.1

ORACLE_SUPPORT_PRODUCT="Oracle Linux"

ORACLE_SUPPORT_PRODUCT_VERSION=10.1

まずは来年、2026年4月にEOLになるMySQL 8.0シリーズの最新版、8.0.44。


$ wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.44.tar.gz

$ tar xf mysql-boost-8.0.44.tar.gz
$ cmake .
-bash: cmake: command not found

$ sudo dnf install -y cmake

$ cmake .
-- Running cmake version 3.30.5
-- Could NOT find Git (missing: GIT_EXECUTABLE)
Hint: The project() command has not yet been called.  It sets up system-specific search paths.
-- This is .el10. as found from 'rpm -qf /'
-- CMAKE_MODULE_PATH is /home/yoku0825/mysql-8.0.44/cmake
-- MySQL 8.0.44
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:585 (PROJECT):
  No CMAKE_C_COMPILER could be found.

  Tell CMake where to find the compiler by setting either the environment
  variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
  the compiler, or to the compiler name if it is in the PATH.

CMake Error at CMakeLists.txt:585 (PROJECT):
  No CMAKE_CXX_COMPILER could be found.

  Tell CMake where to find the compiler by setting either the environment
  variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
  to the compiler, or to the compiler name if it is in the PATH.

-- Configuring incomplete, errors occurred!

コンパイラがないので入れる。去年(Rocky Linux 9.4)の時は「このgcc-toolsetを入れろ」って書いてあったけど10系だからかそんなに親切ではない感じ。

$ sudo dnf install -y gcc gcc-c++

$ cmake .
..
-- Binary directory /home/yoku0825/mysql-8.0.44
CMake Error at CMakeLists.txt:639 (MESSAGE):
  Please do not build in-source.  Out-of source builds are highly
  recommended: you can have multiple builds for the same source, and there is
  an easy way to do cleanup, simply remove the build directory (note that
  'make clean' or 'make distclean' does *not* work)

  You *can* force in-source build by invoking cmake with
  -DFORCE_INSOURCE_BUILD=1

-- Configuring incomplete, errors occurred!

忘れてた。インソースビルドでいいので足す。あとBoost同梱版なのでそれも足す。さらについでにインストール先の指定もくっつける。

$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/8.0.44 -DFORCE_INSOURCE_BUILD=1 -DWITH_BOOST=./boost .
..
-- ZSTD_LEGACY_SUPPORT not defined!
--
Not a supported openssl version in WITH_SSL=system.
Make sure you have specified a supported SSL version.
Valid options are :
openssl[0-9]+ (use alternative system library)
yes (synonym for system)
</path/to/custom/openssl/installation>

CMake Error at cmake/ssl.cmake:84 (MESSAGE):
  Please install the appropriate openssl developer package.

Call Stack (most recent call first):
  cmake/ssl.cmake:406 (FATAL_SSL_NOT_FOUND_ERROR)
  CMakeLists.txt:1848 (MYSQL_CHECK_SSL)

-- Configuring incomplete, errors occurred!

openssl-develが必要、はい。

$ sudo dnf install -y openssl-devel

$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/8.0.44 -DFORCE_INSOURCE_BUILD=1 -DWITH_BOOST=./boost .

..
-- Could NOT find Curses (missing: CURSES_LIBRARY CURSES_INCLUDE_PATH)
CMake Error at cmake/readline.cmake:93 (MESSAGE):
  Curses library not found.  Please install appropriate package,

      remove CMakeCache.txt and rerun cmake.On Debian/Ubuntu, package name is libncurses5-dev, on Redhat and derivates it is ncurses-devel.
Call Stack (most recent call first):
  cmake/readline.cmake:127 (FIND_CURSES)
  cmake/readline.cmake:221 (MYSQL_USE_BUNDLED_EDITLINE)
  CMakeLists.txt:1952 (MYSQL_CHECK_EDITLINE)

-- Configuring incomplete, errors occurred!

ncurses-develも必要。で入れたらCMakeCache.txtを消せと(なんでこのパッケージだけ消さないとダメなのか俺はよくわかっていない…)

$ sudo dnf install -y ncurses-devel
$ rm CMakeCache.txt
$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/8.0.44 -DFORCE_INSOURCE_BUILD=1 -DWITH_BOOST=./boost .
..
-- Checking for module 'libtirpc'
--   Package 'libtirpc', required by 'virtual:world', not found
CMake Warning at cmake/rpc.cmake:41 (MESSAGE):
  Cannot find RPC development libraries.  You need to install the required
  packages:

    Debian/Ubuntu:              apt install libtirpc-dev
    RedHat/Fedora/Oracle Linux: yum install libtirpc-devel
    SuSE:                       zypper install glibc-devel

Call Stack (most recent call first):
  cmake/rpc.cmake:112 (WARN_MISSING_SYSTEM_TIRPC)
  CMakeLists.txt:2088 (MYSQL_CHECK_RPC)

CMake Error at cmake/rpc.cmake:113 (MESSAGE):
  Could not find rpc/rpc.h in /usr/include or /usr/include/tirpc
Call Stack (most recent call first):
  CMakeLists.txt:2088 (MYSQL_CHECK_RPC)

-- Configuring incomplete, errors occurred!

毎年リポジトリがよくわからなくなるtirpc-devel 。Oracle Linux 10では ol10_codeready_builder らしい。

$ sudo dnf install libtirpc-devel

Last metadata expiration check: 0:23:40 ago on Sat 06 Dec 2025 06:44:15 PM JST.
No match for argument: libtirpc-devel
Error: Unable to find a match: libtirpc-devel

$ sudo dnf install -y --enablerepo="*" libtirpc-devel
..
=======================================================================================================================================
 Package                         Architecture            Version                         Repository                               Size
=======================================================================================================================================
Installing:
 libtirpc-devel                  x86_64                  1.3.5-1.el10                    ol10_codeready_builder                  187 k
..

$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/8.0.44 -DFORCE_INSOURCE_BUILD=1 -DWITH_BOOST=./boost .
..

-- Performing Test X_PUTLONG_NOT_USE_CONST - Failed
CMake Warning at cmake/rpc.cmake:30 (MESSAGE):
  Cannot find rpcgen executable.  You need to install the required packages:

    Debian/Ubuntu:              apt install rpcsvc-proto
    RedHat/Fedora/Oracle Linux: yum install rpcgen
    SuSE:                       zypper install glibc-devel

Call Stack (most recent call first):
  plugin/group_replication/libmysqlgcs/cmake/rpcgen.cmake:113 (WARN_MISSING_RPCGEN_EXECUTABLE)
  plugin/group_replication/libmysqlgcs/CMakeLists.txt:51 (INCLUDE)

CMake Error at plugin/group_replication/libmysqlgcs/cmake/rpcgen.cmake:114 (MESSAGE):
  Could not find rpcgen
Call Stack (most recent call first):
  plugin/group_replication/libmysqlgcs/CMakeLists.txt:51 (INCLUDE)

-- Configuring incomplete, errors occurred!

また毎年リポジトリのはぐれるrpcgen

$ sudo dnf install -y --enablerepo="*" rpcgen

..
=======================================================================================================================================
 Package                     Architecture                Version                             Repository                           Size
=======================================================================================================================================
Installing:
 rpcgen                      x86_64                      1.4-17.el10                         ol10_appstream                       55 k
..

$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/8.0.44 -DFORCE_INSOURCE_BUILD=1 -DWITH_BOOST=./boost .
..

-- CMAKE_SHARED_LINKER_FLAGS
-- Configuring done (3.2s)
-- Generating done (5.2s)
-- Build files have been written to: /home/yoku0825/mysql-8.0.44

$ time make -j$(nproc)
..
real    41m31.176s
user    225m37.415s
sys     15m19.890s

$ sudo make install

$ du -sh /usr/mysql/8.0.44/
1.5G    /usr/mysql/8.0.44/

OK。次に今のメインストリームの8.4.7。Boostは同梱されるようになったから -DWITH_BOOST はもういらない。

$ wget https://dev.mysql.com/get/Downloads/MySQL-8.4/mysql-8.4.7.tar.gz
$ tar xf mysql-8.4.7.tar.gz
$ cd mysql-8.4.7/
$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/8.4.7 -DFORCE_INSOURCE_BUILD=1 .

$ time make -j$(nproc)
..
/home/yoku0825/mysql-8.4.7/extra/boost/boost_1_84_0/boost/multiprecision/cpp_bin_float.hpp:40:10: fatal error: quadmath.h: No such file or directory
   40 | #include <quadmath.h>
      |          ^~~~~~~~~~~~
compilation terminated.
make[2]: *** [sql/CMakeFiles/sql_gis.dir/build.make:90: sql/CMakeFiles/sql_gis.dir/gis/buffer.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:49710: sql/CMakeFiles/sql_gis.dir/all] Error 2
make: *** [Makefile:166: all] Error 2

real    39m24.234s
user    217m18.669s
sys     13m42.765s

エラった…。 libquadmath-devel が必要そう。

$ sudo dnf install libquadmath-devel
$ time make -j$(nproc)
..
real    19m49.002s
user    106m29.194s
sys     6m19.764s

合計49分くらい。サイズはそんな変わらない。

$ sudo make install
$ du -sh /usr/mysql/8.4.7/
1.5G    /usr/mysql/8.4.7/

最後にInnovation Releaseの9.5.0

$ wget https://dev.mysql.com/get/Downloads/MySQL-9.5/mysql-9.5.0.tar.gz

$ tar xf mysql-9.5.0.tar.gz
$ cd mysql-9.5.0/
$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/9.5.0 -DFORCE_INSOURCE_BUILD=1 .
..
-- Could NOT find BISON (missing: BISON_EXECUTABLE)
CMake Warning at cmake/bison.cmake:119 (MESSAGE):
  No bison found!!
Call Stack (most recent call first):
  router/src/routing_guidelines/src/CMakeLists.txt:25 (INCLUDE)

CMake Warning at cmake/bison.cmake:120 (MESSAGE):
  If you have bison in a non-standard location, you can do 'cmake
  -DBISON_EXECUTABLE=</path/to/bison-executable>
Call Stack (most recent call first):
  router/src/routing_guidelines/src/CMakeLists.txt:25 (INCLUDE)

CMake Error at /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:233 (message):
  Could NOT find BISON (missing: BISON_EXECUTABLE)
Call Stack (most recent call first):
  /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:603 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake/Modules/FindBISON.cmake:306 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  router/src/routing_guidelines/src/CMakeLists.txt:27 (FIND_PACKAGE)

-- Configuring incomplete, errors occurred!

Bisonが必須になったみたい(以前は任意でワーニングは出たけどエラーではなかった)

$ sudo dnf install -y bison
$ cmake -DCMAKE_INSTALL_PREFIX=/usr/mysql/9.5.0 -DFORCE_INSOURCE_BUILD=1 .

$ time make -j$(nproc)
..
real    59m43.890s
user    328m0.973s
sys     19m57.807s

6コア使って1時間じゃ、1コアだとホントにメモリも足りないしダメなんではなかろうか。。

$ du -sh /usr/mysql/9.5.0/
1.6G    /usr/mysql/9.5.0/
明日は ConoHa - Qiita Advent Calendar 2025 が @che_azure さん、 MySQL - Qiita Advent Calendar 2025 が @HrsUed さんです! ​
a

2025/12/04

自分のためのMySQLのSandboxが欲しかったのでyt-sandboxを作った

この記事は MySQL - Qiita Advent Calendar 2025 の4日目の記事です。
昨日は @meijik さんの 各ご家庭(Firebird/MySQL/PostgreSQL)のUUID事情(主に4と7)でした。


MySQLで自分用のサンドボックス環境…といえば長年 MySQL::Sandbox というのがあって、mysqldのバイナリさえあればある程度好きにバカバカとバージョン違いのプロセスを起動したり、 make_replication_sandbox だけで好きにレプリケーションクラスタ一式を起動したりということができました。これはもうだいぶ前にメンテナンスが終わっていて、確か8.0くらいは軽くゴニョって使えたけど8.4はもう無理という代物。

その後継として同じ人が dbdeployer というのを出していたけれど、8.4で MySQL::SandBoxが完全に使えなくなったら引っ越そうかなと思ったら引っ越す前にメンテナンスが終わった。

まだ生きてるサンドボックス作成ツールとして MySQL Shell の dba.deploySandboxInstance も使ったりはするけどこれは単発でmysqldを(自分でポートを指定して)起動するだけで、レプリケーションを勝手に組んだりしてくれないのでちょっとこの用途としてはちょっと合わない。
当時はmysqldは勝手に /usr/sbin/mysqld とかから探されてしまったけど、最近のリリースで mysqlPath というmysqldバイナリのパスを指定できるようになったのでまたそのうち使い始めるかもしれない。

というわけで、自分用に作りました yt-sandbox
ytkit のスクリプトなので

$ git clone https://github.com/yoku0825/ytkit.git
$ cd ytkit
$ cpanm --installdeps .
$ bin/yt-sandbox

で使えるようになりますが、飽くまで自分で使う用途がメインなので中身でrootless dockerに依存して、dockerのデフォルトネットワークがbridgeでないと動かないとかそんな諸々があります。

シンプルな使い方。

$ bin/yt-sandbox --mysqld=5.5
[7729] NOTE: Generate Sandbox directry into /home/yoku0825/yt-sandbox/alpha
[7729] NOTE: Node1 Container Ipaddress: 172.17.0.2
Sandbox deployed into /home/yoku0825/yt-sandbox/alpha

--mysqld でバージョンを渡すとそのタグのコンテナイメージで docker run します。普通に docker run で指定するだけなので、 8.4.5時代に 8.4 で起動していると 8.4 のタグが 8.4.5 に向いたままとか起こるような気がします。なお、 latest は対応してません。
古めのバージョンは Docker Hub から、新しめのバージョンはOracleのコンテナハブからダウンロードしてきます。

ターミナルにも出力しますが、サンドボックスディレクトリを作ってその中に色々ぶち込みます。

$ cd /home/yoku0825/yt-sandbox/alpha
$ ll
total 28
-rw-r--r-- 1 yoku0825 yoku0825   98 Dec  4 10:27 destroy_all
-rw-r--r-- 1 yoku0825 yoku0825   19 Dec  4 10:27 hosts
lrwxrwxrwx 1 yoku0825 yoku0825   41 Dec  4 10:27 n1 -> /home/yoku0825/yt-sandbox/alpha/node1/use
drwxr-xr-x 3 yoku0825 yoku0825 4096 Dec  4 10:27 node1
-rwxr-xr-x 1 yoku0825 yoku0825   98 Dec  4 10:27 restart_all
-rwxr-xr-x 1 yoku0825 yoku0825   96 Dec  4 10:27 start_all
-rwxr-xr-x 1 yoku0825 yoku0825   95 Dec  4 10:27 stop_all
-rwxr-xr-x 1 yoku0825 yoku0825   94 Dec  4 10:27 use_all

MySQL::Sandboxはこのディレクトリにちゃんと use とかがあったんですが、yt-sandboxはサーバー数が1かそれ以上かを区別しないので use とかは個別の node1 ディレクトリの中に入ってます。

単発のインスタンスで良ければdockerコマンド単体で上げちゃうのでこれはあんまり使っていないかも。

$ yt-sandbox -t replication --servers 2
[8333] NOTE: Generate Sandbox directry into /home/yoku0825/yt-sandbox/charlie
Unable to find image 'container-registry.oracle.com/mysql/community-server:8.4' locally
8.4: Pulling from mysql/community-server
c1796c1f2872: Pull complete
73dc7709f5dd: Pull complete
3ba20a201270: Pull complete
bcf1148c6894: Pull complete
ea899417b705: Pull complete
017f83ce814a: Pull complete
d120c25676a4: Pull complete
Digest: sha256:5e274b0e244563921fe9b520f4a2dec301ffc4fc81164a362c6cb3dac60255a9
Status: Downloaded newer image for container-registry.oracle.com/mysql/community-server:8.4
[8333] NOTE: Node1 Container Ipaddress: 172.17.0.2
[8333] NOTE: Node2 Container Ipaddress: 172.17.0.3
Sandbox deployed into /home/yoku0825/yt-sandbox/charlie

-t replication でレプリケーションクラスタを作れます。 -t gr (Group Replication) もあります。
--servers でクラスタトータルの台数を指定できます。↑の場合はソースレプリカ足して2なので1台ずつ作成されます。

$ cd /home/yoku0825/yt-sandbox/charlie
$ ll
total 36
-rwxr-xr-x 1 yoku0825 yoku0825  259 Dec  4 10:39 check_replication
-rw-r--r-- 1 yoku0825 yoku0825  100 Dec  4 10:39 destroy_all
-rw-r--r-- 1 yoku0825 yoku0825   42 Dec  4 10:39 hosts
lrwxrwxrwx 1 yoku0825 yoku0825   43 Dec  4 10:39 m -> /home/yoku0825/yt-sandbox/charlie/node1/use
drwxr-xr-x 3 yoku0825 yoku0825 4096 Dec  4 10:39 node1
drwxr-xr-x 3 yoku0825 yoku0825 4096 Dec  4 10:39 node2
-rwxr-xr-x 1 yoku0825 yoku0825  100 Dec  4 10:39 restart_all
lrwxrwxrwx 1 yoku0825 yoku0825   43 Dec  4 10:39 s1 -> /home/yoku0825/yt-sandbox/charlie/node2/use
-rwxr-xr-x 1 yoku0825 yoku0825   98 Dec  4 10:39 start_all
-rwxr-xr-x 1 yoku0825 yoku0825   97 Dec  4 10:39 stop_all
-rwxr-xr-x 1 yoku0825 yoku0825   96 Dec  4 10:39 use_all

MySQL::Sandbox っぽく、 ./m でソースにつながったり、 ./s1 でレプリカに繋がったりします。最初から gtid_mode=ON です。

レプリケーションはIPアドレスに依存していて、dockerコンテナは上げたり下げたりするとIPアドレスが変わる(俺はそういう使い方しかしていない)ので、一度でもstopするとレプリケーションは壊れることがあります。

基本は、

  • 作って
  • 試して
  • すぐ捨てる
    がコンセプトです。

root@% がパスワードなしで公開されているので注意してください。サンドボックスです。

明日は @taka_yuki_04 さんです!

2025/09/08

大吉祥寺.pm 2025はとても最高でした

大吉祥寺.pm 2025 に参加してきました。まずは最高でした。主催の @magnoliak さん、スタッフのみなさま、登壇者のみなさま、参加されたみなさま、懇親会のお店のみなさまみんなどうもありがとうございました!

新型コロナウイルスが世を騒がせた2020年から、外に出てしゃべる機会が激減し、たまにオンラインでやったり、年に1回くらいは外で何かしゃべったり…。そんな生活が4年くらい続いていました。
今年に入ってから以前みたいに活動したいなと強く思っていて、 HeatwaveJP , db tech showcase 2025 Tokyo でしゃべらせてもらって「今年はちょくちょくしゃべってるな、ペース戻ってきたかな」とか思ってたんですが。
どちらもお招きいただいたもので、オフラインでプロポーザルを書いて参加したイベントはたぶん5年前の PHPerKaigi 2020 以来。
もともとプロポーザルを書くのは全然上手くないのですが、 転職 から1か月半時点で溜まりに溜まった「MariaDBに違和感を感じるなんて、俺はそんなにMySQLが好きだったんだな」感を伝えたくて ( 「2025年の今、みんなに聞いてほしいこと」 今、誰かに言っておきたいこと 「あの時、こんなこと言ってたなぁ、2025年っぽいー」 ) 応募しました。

きちぴーへの参加は大のつかない 吉祥寺.pm11 以来8年ぶり(!!) 2回目でした。もう8年も経っていたの!?

採択いただいて喜ぶ俺の図。

久々のプロポーザル、久々の吉祥寺(俺は高校が吉祥寺駅に近かったので、昔はよく遊びに来ていたものなんです)、そして久々の @magnoliak さんと三拍子揃った嬉しい登壇でした。
magnoliakさんとは個人的に心の同期感があって、 2015年のYAPC::Asia 2015のLTでご一緒した仲 なので、またこうやって同じ会場で話す機会がいただけたのはすごく嬉しく思っています。



(まだ当時の動画が見られます。維持してくれていてとてもありがたい…。)

そんな私のセッションはこんな感じでした。

すばらしいまとめ(ツイートが多すぎて当日自分では到底終えなかった。朝イチだったのでその後もガンガン流れていく)を作っていただけたので、なんとなく雰囲気を感じていただけると嬉しいです。
物語のクライマックスは冒頭3分~5分くらいでスライドがちゃんと映るようになったところでした。あの拍手が無ければ俺はきっとフリーズしていたでしょう。。

大吉祥寺.pm 2025 のまとめ #kichijojipm - posfie

ちょうど本業でMariaDBとMySQLのことを思って誰かに話したい気分だったことと、調べてみたら以前(俺がMariaDBを真面目に比較していたのは10.0くらいの時までだった)と割と状況が違っていたので、そのあたり昔話や経緯も含めてざっとまとめられたかなと思っています。

なお、ランチマッチングで若者とカレーを食べに行きました(俺が高校生だった25年前とかに行ったことがあるお店な気がする。建物にはあんまりピンと来ませんでしたが確かあんなお店の名前だったような…)

セッショントークも面白かったし、ライトニングトークは本当に笑わせてもらいました。カンパもしました。いい一日だった!

みなさん本当にありがとうございました!

2025/07/04

最新のMySQL ShellだけでMySQLのPITR可能なバックアップを設定する(実践編)

日々の覚書: 最新のMySQL ShellだけでMySQLのPITR可能なバックアップを設定する(増分バックアップ編) の更に続き。

フェイルオーバー、ソース切り替えが起こって gtid_executed が複数行になった時にどうなるのかを調べる。

昨日リストアした172.17.0.3 に更にsysbenchでちょっと更新をかけながらハートビートテーブルにも書かせていた。


mysql> SHOW BINARY LOG STATUS;

+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+

| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                         |

+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+

| binlog.000003 | 48101470 |              |                  | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,

8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1686 |

+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

切り替わりが発生すると、それまで積み重ねてきたバイナリログのバックアップに追加することはできなくなる。おそらく切り替わったらフルバックアップを取り直してそこからまたバイナリログを積み上げるのが良さそう。

$ mysqlsh -h 172.17.0.3 -uroot --no-password --js -- util dumpBinlogs /path/to/binlog_backup
WARNING: Using a password on the command line interface can be insecure.
ERROR: ArgumentError: The source instance is different from the one used in the previous dump and it's not part of an InnoDB Cluster group.

gtid_mode=ON なら切り替わりをまたぐPITRでも他のノードで log_replica_updates によって十分なバイナリログが残っていれば(実行済みの gtid_next はスキップされるのでGTIDに隙間ができないように余裕をもって指定すれば良いだけで、完全にGTIDの切れ目で一致させる必要はない)楽なんだけれども、今検証しているこれの範疇からは外れそう。

$ mysqlsh -h 172.17.0.3 -uroot --no-password --js -- util dumpInstance /path/to/another_full_backup/
WARNING: Using a password on the command line interface can be insecure.
Acquiring global read lock
Global read lock acquired
Initializing - done
2 out of 6 schemas will be dumped and within them 2 tables, 0 views.
4 out of 7 users will be dumped.
Gathering information - done
All transactions have been started
Locking instance for backup
Global read lock has been released
Writing global DDL files
Writing users DDL
Running data dump using 4 threads.
NOTE: Progress information uses estimated values and may not be accurate.
Writing schema metadata - done
Writing DDL - done
Writing table metadata - done
Starting data dump
101% (1.08M rows / ~1.06M rows), 536.44K rows/s, 99.41 MB/s uncompressed, 44.03 MB/s compressed
Dump duration: 00:00:02s
Total duration: 00:00:02s
Schemas dumped: 2
Tables dumped: 2
Uncompressed data size: 200.43 MB
Compressed data size: 88.74 MB
Compression ratio: 2.3
Rows written: 1077870
Bytes written: 88.74 MB
Average uncompressed throughput: 95.47 MB/s
Average compressed throughput: 42.27 MB/s

$ mysqlsh -h 172.17.0.3 -uroot --no-password --js -- util dumpBinlogs /path/to/another_binlog { --since=/path/to/another_full_backup/ }
WARNING: Using a password on the command line interface can be insecure.
Starting from previous dump: /path/to/another_full_backup, created at: 2025-07-04 02:28:23 UTC
Starting from binary log file: binlog.000003:48101470
Will finish at binary log file: binlog.000003:48107225
Dumping 1 binlogs (5.75 KB of data) using 4 threads
102% (5.88 KB / 5.75 KB), 0.00 B/s, 0.00 B/s compressed, 1 / 1 binlogs done
Dump was written to: /path/to/another_binlog/2025-07-04-03-31-48
Total duration: 00:00:00s
Binlogs dumped: 1
GTID set dumped: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1687-1701
Uncompressed data size: 5.88 KB
Compressed data size: 1.39 KB
Compression ratio: 4.2
Events written: 70
Bytes written: 1.39 KB
Average uncompressed throughput: 5.88 KB/s
Average compressed throughput: 1.39 KB/s

話は変わるけど、バイナリログを吸い上げたディレクトリの中の日付のディレクトリの中に、「この util.dumpBinlogs が終わった時点での最後のバイナリログファイル名とポジション、 gtid_executed 」がメタデータとして吸い上げられていることに気が付いた。

$ ll binlog/2025-07-04-02-45-04/
total 140
-rw-r-----. 1 yoku0825 yoku0825    42 Jul  4 02:45 @.binlog.done.json
-rw-r-----. 1 yoku0825 yoku0825 47356 Jul  4 02:45 @.binlog.json
-rw-r-----. 1 yoku0825 yoku0825   329 Jul  4 02:45 binary-log.043707.json
-rw-r-----. 1 yoku0825 yoku0825  7116 Jul  4 02:45 binary-log.043707.zst
-rw-r-----. 1 yoku0825 yoku0825   303 Jul  4 02:45 binary-log.043708.json
-rw-r-----. 1 yoku0825 yoku0825 22974 Jul  4 02:45 binary-log.043708.zst
-rw-r-----. 1 yoku0825 yoku0825   303 Jul  4 02:45 binary-log.043709.json
-rw-r-----. 1 yoku0825 yoku0825 23087 Jul  4 02:45 binary-log.043709.zst
-rw-r-----. 1 yoku0825 yoku0825   330 Jul  4 02:45 binary-log.043710.json
-rw-r-----. 1 yoku0825 yoku0825 15741 Jul  4 02:45 binary-log.043710.zst

$ jq .endAt binlog/2025-07-04-02-45-04/@.binlog.json
{
  "file": "binary-log.043710",
  "position": 103420,
  "gtidExecuted": "9330ac0f-e14a-11ef-a07c-0200170681c1:1-2455837"
}

話を戻して、切り替わったソースから取ったバイナリログでPITRできるかの話。

$ mysql -h172.17.0.4 -uroot -e "SET GLOBAL local_infile=1"
$ mysqlsh root@172.17.0.4 --js -- util loadDump /path/to/another_full_backup/ { --loadUsers=true --ignoreExistingObjects=true --updateGtidSet=replace --skipBinlog=true }

$ mysql -h172.17.0.4 -uroot -e "SELECT * FROM sakura.hb ORDER BY seq DESC LIMIT 1"
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| seq   | hostname     | recorded            | gtid_executed                                                                             |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| 77870 | 756eebf85ccb | 2025-07-03 05:50:33 | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1685 |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+

$ mysql -h172.17.0.4 -uroot -e "RESTART"

たとえば7/4 03:34(UTC) に着地したい場合は、バックアップ元でこんな風に引くことを 前回 やっていたけれど、

$ mysql -h172.17.0.3 -e "SELECT * FROM sakura.hb WHERE recorded = '2025-07-04 03:34:00'"
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| seq   | hostname     | recorded            | gtid_executed                                                                             |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| 78015 | 756eebf85ccb | 2025-07-04 03:34:00 | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1832 |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+

$ mysqlsh root@172.17.0.4 --js -- util loadBinlogs /path/to/another_binlog { --stopAfter="3b5d02fb-56e7-11f0-8f01-0242ac110002:87887" }   ### こっちは最初のソース172.17.0.2が持っていたGTIDの末尾
Please provide the password for 'root@172.17.0.4':
Save password for 'root@172.17.0.4'? [Y]es/[N]o/Ne[v]er (default No):
ERROR: ArgumentError: Could not find the final binary log file to be loaded that contains GTID '3b5d02fb-56e7-11f0-8f01-0242ac110002:87887'.

$ mysqlsh root@172.17.0.4 --js -- util loadBinlogs /path/to/another_binlog { --stopAfter="8e7dfcc0-57b7-11f0-a722-0242ac110003:1832" }   ### こっちが直接バックアップを取った172.17.0.3が持っていた(復元したい)GTIDの末尾
Please provide the password for 'root@172.17.0.4':
Save password for 'root@172.17.0.4'? [Y]es/[N]o/Ne[v]er (default No):
Loading 2 binlogs, 112.52 KB of data
Opening dump '/path/to/another_binlog'
  Loading dump '2025-07-04-03-31-48' created at 2025-07-04 03:31:48 UTC
    Loading binary log file 'binlog.000003', GTID set: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1687-1701 (5.88 KB)
      Found starting GTID: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1687
  Loading dump '2025-07-04-03-36-11' created at 2025-07-04 03:36:11 UTC
    Loading binary log file 'binlog.000003', GTID set: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1702-1964 (106.64 KB)
      Stopped after GTID: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1832
56% (63.23 KB / 112.52 KB), 0.00 B/s, 0.00 B/s compressed, 0.00 stmts/s, 2 / 2 binlogs done
Total duration: 00:00:00s
Binlogs loaded: 2
Uncompressed data size: 112.52 KB
Compressed data size: 16.59 KB
Statements executed: 1330
Average uncompressed throughput: 63.23 KB/s
Average compressed throughput: 16.59 KB/s
Average statement throughput: 1.33 KB/s

$ mysql -h172.17.0.4 -uroot -e "SELECT * FROM sakura.hb ORDER BY seq DESC LIMIT 1"
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| seq   | hostname     | recorded            | gtid_executed                                                                             |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| 78014 | 756eebf85ccb | 2025-07-04 03:33:59 | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1831 |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+

$ mysql -h172.17.0.4 -uroot -e "SHOW BINARY LOG STATUS"
+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                         |
+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+
| binlog.000002 |    59702 |              |                  | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1832 |
+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+

その時の @@server_uuid の値はバイナリログのディレクトリに残ってるので、アプリケーションとかでパースするならこれを使える気がする。

$ jq . /path/to/another_binlog/@.binlog.info.json
{
  "dumper": "mysqlsh Ver 9.3.0 for Linux on x86_64 - for MySQL 9.3.0 (MySQL Community Server (GPL))",
  "version": "2.0.1",
  "origin": "dumpBinlogs",
  "timestamp": "2025-07-04 03:31:48",
  "source": {
    "version": "8.4.5",
    "hostname": "756eebf85ccb",
    "port": 3306,
    "serverUuid": "8e7dfcc0-57b7-11f0-a722-0242ac110003",
    "topology": {
      "canonicalAddress": "756eebf85ccb:3306"
    }
  }
}

が、あんまり凝ったことはしたくないのでハートビートテーブルから取り出すことにする。

### ターゲットはこれ
mysql> SELECT * FROM sakura.hb WHERE recorded = '2025-07-04 03:34:00';
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| seq   | hostname     | recorded            | gtid_executed                                                                             |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| 78015 | 756eebf85ccb | 2025-07-04 03:34:00 | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1832 |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
1 row in set (0.04 sec)

### 少し前の(直近でもいい)レコードを取り出す。単一のGTIDだけが取り出されると話が終わっちゃうのでレンジになるように少し前のレコードにしているだけ
mysql> SELECT * FROM sakura.hb WHERE recorded < '2025-07-04 03:33:00' ORDER BY recorded DESC LIMIT 1;
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| seq   | hostname     | recorded            | gtid_executed                                                                             |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| 77954 | 756eebf85ccb | 2025-07-04 03:32:59 | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1771 |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
1 row in set (0.05 sec)

### 両者を比較する
mysql> SELECT GTID_SUBTRACT((SELECT gtid_executed FROM sakura.hb WHERE recorded = '2025-07-04 03:34:00'), (SELECT gtid_executed FROM sakura.hb WHERE recorded < '2025-07-04 03:33:00' ORDER BY recorded DESC LIMIT 1)) AS diff;
+------------------------------------------------+
| diff                                           |
+------------------------------------------------+
| 8e7dfcc0-57b7-11f0-a722-0242ac110003:1772-1832 |
+------------------------------------------------+
1 row in set (0.09 sec)

グループレプリケーションのマルチプライマリーモードやマルチソースレプリケーション、この時間の間にフェイルオーバーが走っていなければここで抽出されるGTIDは単一の server_uuid になるはず。

となれば :- で切り出せば最後の1つは出せる。

mysql> SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(GTID_SUBTRACT((SELECT gtid_executed FROM sakura.hb WHERE recorded = '2025-07-04 03:34:00'), (SELECT gtid_executed FROM sakura.hb WHERE recorded < '2025-07-04 03:33:00' ORDER BY recorded DESC LIMIT 1)), ':', -1), '-', -1) AS last_gtid_seq;
+---------------+
| last_gtid_seq |
+---------------+
| 1832          |
+---------------+
1 row in set (0.08 sec)

mysql> SELECT CONCAT(@@server_uuid, ':', SUBSTRING_INDEX(SUBSTRING_INDEX(GTID_SUBTRACT((SELECT gtid_executed FROM sakura.hb WHERE recorded = '2025-07-04 03:34:00'), (SELECT gtid_executed FROM sakura.hb
WHERE recorded < '2025-07-04 03:33:00' ORDER BY recorded DESC LIMIT 1)), ':', -1), '-', -1)) AS last_gtid;
+-------------------------------------------+
| last_gtid                                 |
+-------------------------------------------+
| 657f3412-588a-11f0-9230-0242ac110003:1832 |
+-------------------------------------------+
1 row in set (0.08 sec)

これで dump.loadBinlogs に渡す引数が完成した気がする。

もう一つコンテナを起動して、

$ mysql -h172.17.0.5 -uroot -e "SET GLOBAL local_infile=1"
$ mysqlsh root@172.17.0.5 --js -- util loadDump /path/to/another_full_backup/ { --loadUsers=true --ignoreExistingObjects=true --updateGtidSet=replace --skipBinlog=true }

$ mysqlsh root@172.17.0.5 --js -- util loadBinlogs /path/to/another_binlog { --stopAfter=$(mysql -h172.17.0.3 -uroot -sse "SELECT CONCAT(@@server_uuid, ':', SUBSTRING_INDEX(SUBSTRING_INDEX(GTID_SUBTRACT((SELECT gtid_executed FROM sakura.hb WHERE recorded = '2025-07-04 03:34:00'), (SELECT gtid_executed FROM sakura.hb WHERE recorded < '2025-07-04 03:33:00' ORDER BY recorded DESC LIMIT 1)), ':', -1), '-', -1)) AS last_gtid;") }
Please provide the password for 'root@172.17.0.5':
Save password for 'root@172.17.0.5'? [Y]es/[N]o/Ne[v]er (default No):
Loading 2 binlogs, 112.52 KB of data
Opening dump '/path/to/another_binlog'
  Loading dump '2025-07-04-03-31-48' created at 2025-07-04 03:31:48 UTC
    Loading binary log file 'binlog.000003', GTID set: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1687-1701 (5.88 KB)
      Found starting GTID: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1687
  Loading dump '2025-07-04-03-36-11' created at 2025-07-04 03:36:11 UTC
    Loading binary log file 'binlog.000003', GTID set: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1702-1964 (106.64 KB)
      Stopped after GTID: 8e7dfcc0-57b7-11f0-a722-0242ac110003:1832
56% (63.23 KB / 112.52 KB), 0.00 B/s, 0.00 B/s compressed, 0.00 stmts/s, 2 / 2 binlogs done
Total duration: 00:00:00s
Binlogs loaded: 2
Uncompressed data size: 112.52 KB
Compressed data size: 16.59 KB
Statements executed: 1330
Average uncompressed throughput: 63.23 KB/s
Average compressed throughput: 16.59 KB/s
Average statement throughput: 1.33 KB/s

$ mysql -h172.17.0.5 -uroot -e "SELECT * FROM sakura.hb ORDER BY seq DESC LIMIT 1"
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| seq   | hostname     | recorded            | gtid_executed                                                                             |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+
| 78014 | 756eebf85ccb | 2025-07-04 03:33:59 | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1831 |
+-------+--------------+---------------------+-------------------------------------------------------------------------------------------+

$ mysql -h172.17.0.5 -uroot -e "SHOW BINARY LOG STATUS"
+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                         |
+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+
| binlog.000002 |    59702 |              |                  | 3b5d02fb-56e7-11f0-8f01-0242ac110002:1-87887,
8e7dfcc0-57b7-11f0-a722-0242ac110003:1-1832 |
+---------------+----------+--------------+------------------+-------------------------------------------------------------------------------------------+

OKいけた。