TL;DR
RESTART
ステートメントの本質は「終了コード16でmysqld
を停止」するだけ- 親プロセス(
mysqld_safe
,systemd
,dockerd
とかとか) が「終了コード16の時はもう一度mysqld
を起動する」という実装をしなければならない
- 親プロセス(
RESTART
ステートメントの処理の中で、「SHUTDOWN
権限があるか」「MYSQLD_PARENT_PID
環境変数がセットされているか」を判定してから、SIGUSR2
シグナルを使って終了コード16での終了に持っていく- 8.0.20までのDockerイメージの
entrypoint.sh
はMYSQLD_PARENT_PID
を渡していなかったので、その評価のところでfalseになってRESTART
はエラーを返していた - 8.0.21からの
entrypoint.sh
はこれを設定するようになったのでRESTART
ステートメントから「終了コード16で停止」まではわたる。それを起動するにはdocker run --restart=on-failure
にすること(でないと、RESTART
ステートメントがmysqld
を停止したところでコンテナが止まって再起動にはならない) - 「上位プロセスが
mysqld
を起動しなおす」ということを押さえておけば、MYSQLD_PARENT_PID
を渡すだけなので汎用性は高そう
- 8.0.20までのDockerイメージの
RESTART
ステートメントを叩き込むと、 mysql_execute_command
, Sql_cmd_restart_server::execute
, signal_restart_server
を通って __pthread_kill
でsignel 12(= SIGUSR2
)が呼ばれる。
(gdb) b pthread_kill
+b pthread_kill
Breakpoint 1 at 0x7fcb07702a70: file ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c, line 40.
(gdb) c
+c
(gdb) bt
+bt
#0 __pthread_kill (threadid=140509764310784, signo=signo@entry=12) at ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c:40
#1 0x0000000000dadf0a in signal_restart_server () at /home/yoku0825/mysql-8.0.21/sql/mysqld.cc:2330
#2 0x0000000000efa1bd in Sql_cmd_restart_server::execute(THD*) () at /home/yoku0825/mysql-8.0.21/sql/sql_restart_server.cc:78
#3 0x0000000000ead21f in mysql_execute_command(THD*, bool) () at /home/yoku0825/mysql-8.0.21/sql/sql_parse.cc:4573
#4 0x0000000000eb217f in mysql_parse (thd=thd@entry=0x7fcaac0d0390, parser_state=parser_state@entry=0x7fcafa924510)
at /home/yoku0825/mysql-8.0.21/sql/sql_parse.cc:5393
#5 0x0000000000eb42c0 in dispatch_command(THD*, COM_DATA const*, enum_server_command) ()
at /home/yoku0825/mysql-8.0.21/sql/sql_parse.cc:1810
#6 0x0000000000eb5034 in do_command (thd=thd@entry=0x7fcaac0d0390) at /home/yoku0825/mysql-8.0.21/sql/sql_parse.cc:1294
#7 0x0000000000fcd330 in handle_connection (arg=arg@entry=0x62ab490)
at /home/yoku0825/mysql-8.0.21/sql/conn_handler/connection_handler_per_thread.cc:302
#8 0x000000000260c2be in pfs_spawn_thread (arg=0x62e7040) at /home/yoku0825/mysql-8.0.21/storage/perfschema/pfs.cc:2880
#9 0x00007fcb076fdea5 in start_thread (arg=0x7fcafa925700) at pthread_create.c:307
#10 0x00007fcb05ae18dd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
mysqld
は SIGUSR2
を受け取ると signal_hand_thr_exit_code = MYSQLD_RESTART_EXIT
をセットして ( MYSQLD_RESTART_EXITは16 ) 終了する ( case
の中で break
しないのでそのまま SIGTERM
, SIGQUIT
と同じ処理に流れる)
たとえば mysqld_safe
はこんな風に終了コードを見て、再起動するかそのまま正常終了するかを決めていたりする。
このへんの仕組みを知っていれば、標準以外の環境でも RESTART
ステートメントを使えるようにするにできる気がする。