GA

2022/09/12

MySQL 8.0.30でもrpl_semi_sync_master_enabledとrpl_semi_sync_source_enabledは同じものではない

TL;DR

  • rpl_semi_sync_master_enabledsemisync_master.so 由来で rpl_semi_sync_source_eanbledsemisync_source.so 由来
    • 他のMaster/Source系と違って、MySQLサーバーの中で丸められているわけではなく、 INSTALL PLUGIN した時にどちらを入れたかに依存する

rpl_semi_sync_master_enabledrpl_semi_sync_source_eanbled (enabledに限らず、 rpl_semi_sync_* な設定は全て) は INSTALL PLGUIN した .soファイルに依存するので、MySQL 8.0.30現在、SOURCE, MASTERの用語変更が行われたバージョンであってもこれらは勝手には翻訳されない( semisync_master.so をINSTALLした場合、 rpl_semi_sync_master_* を使用するしかなくて、 rpl_semi_sync_source_* で設定しようとすると unknown variable って怒られる)

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+-------+------+-----------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                               |
+-------+------+-----------------------------------------------------------------------------------------------------------------------+
| Note  | 1287 | 'rpl_semi_sync_master' is deprecated and will be removed in a future release. Please use rpl_semi_sync_source instead |
+-------+------+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | OFF        |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)
mysql> INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW VARIABLES LIKE '%semi%';
+---------------------------------------------+------------+
| Variable_name                               | Value      |
+---------------------------------------------+------------+
| rpl_semi_sync_source_enabled                | OFF        |
| rpl_semi_sync_source_timeout                | 10000      |
| rpl_semi_sync_source_trace_level            | 32         |
| rpl_semi_sync_source_wait_for_replica_count | 1          |
| rpl_semi_sync_source_wait_no_replica        | ON         |
| rpl_semi_sync_source_wait_point             | AFTER_SYNC |
+---------------------------------------------+------------+
6 rows in set (0.00 sec)

ちなみに両方入れようとすると怒られる。

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
ERROR 4045 (HY000): Cannot install the rpl_semi_sync_master plugin when the rpl_semi_sync_source plugin is installed.

semisync_sourcesemisync_slave みたいな混ぜたパターンもできる(ややこしいからやめた方が良い気がする)

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+-----------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                               |
+-------+------+-----------------------------------------------------------------------------------------------------------------------+
| Note  | 1287 | 'rpl_semi_sync_slave' is deprecated and will be removed in a future release. Please use rpl_semi_sync_replica instead |
+-------+------+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE '%semi%';
+---------------------------------------------+------------+
| Variable_name                               | Value      |
+---------------------------------------------+------------+
| rpl_semi_sync_slave_enabled                 | OFF        |
| rpl_semi_sync_slave_trace_level             | 32         |
| rpl_semi_sync_source_enabled                | OFF        |
| rpl_semi_sync_source_timeout                | 10000      |
| rpl_semi_sync_source_trace_level            | 32         |
| rpl_semi_sync_source_wait_for_replica_count | 1          |
| rpl_semi_sync_source_wait_no_replica        | ON         |
| rpl_semi_sync_source_wait_point             | AFTER_SYNC |
+---------------------------------------------+------------+
8 rows in set (0.00 sec)

やろうと思う人がいるとも思えないしすぐエラーになるけど、 semisync_master.sorpl_semi_sync_source をインストールしようとしてもエラる。

mysql> INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_master.so';
ERROR 1127 (HY000): Can't find symbol 'rpl_semi_sync_source' in library

「8.0.28なのに SET GLOBAL rpl_semi_sync_source_enabled=OFF が効かないぞ?」って思ったので残しておきます。

2022/08/30

MySQL on Windowsで8.0.20とそれ以降のmysqld.exeが--skip-grant-tablesでクラッシュすることがある

TL;DR

  • パラメーターの組み合わせを間違えた場合、本来Abortして起動しないもの(ここまでは意図的)がAbortの処理に失敗してクラッシュする
  • skip-grant-tablesしたい時はmy.iniに一緒にshared-memoryを書いてね!

MySQL 8.0では skip-grant-tables を設定した時に自動で skip-networking も設定されるようになった。

これ自体は、「権限テーブル無視してノーガード状態(どこからでもroot相当の権限でノーパスワードでログインできる)のMySQLを守る」ためなので妥当な変更だと思う。

が、Linuix系のMySQLはskip-networkingでもソケット接続が自動(?)で残るので問題ないが、WindowsのMySQLはデフォルトではTCP/IP接続しか使えない = skip-networkingだけを指定するとアクセス方法が全断するのでAbortする。

↓クラッシュしない8.0.19のAbortのログ。

C:\Users\yoku0825\Downloads\mysql-8.0.19-winx64\mysql-8.0.19-winx64>bin\mysqld --console --skip-grant-tables
2022-08-30T02:13:13.537027Z 0 [System] [MY-010116] [Server] C:\Users\yoku0825\Downloads\mysql-8.0.19-winx64\mysql-8.0.19-winx64\bin\mysqld.exe (mysqld 8.0.19) starting as process 11792
2022-08-30T02:13:14.070774Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-08-30T02:13:14.086299Z 0 [System] [MY-010931] [Server] C:\Users\yoku0825\Downloads\mysql-8.0.19-winx64\mysql-8.0.19-winx64\bin\mysqld.exe: ready for connections. Version: '8.0.19'  socket: ''  port: 0  MySQL Community Server - GPL.
2022-08-30T02:13:14.086409Z 0 [ERROR] [MY-010131] [Server] TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS
2022-08-30T02:13:14.086814Z 0 [ERROR] [MY-010119] [Server] Aborting
2022-08-30T02:13:14.271648Z 0 [Warning] [MY-011311] [Server] Plugin mysqlx reported: 'All I/O interfaces are disabled, X Protocol won't be accessible'
2022-08-30T02:13:15.239054Z 0 [System] [MY-010910] [Server] C:\Users\yoku0825\Downloads\mysql-8.0.19-winx64\mysql-8.0.19-winx64\bin\mysqld.exe: Shutdown complete (mysqld 8.0.19)  MySQL Community Server - GPL.

Windowsで非TCP/IP通信をするには shared-memory (これは俺使ったことある)または named-pipe (なんか使うのに失敗して以来使ってない) を「明示的に」my.iniに追加しないといけない。

追加していない場合、 [ERROR] [MY-010131] [Server] TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS (skip-networkingによって)TCP/IPも有効じゃないし、shared-memoryもnamed-pipeも1つも有効になってないよ(少なくとも1つは有効にしろよ)とエラーになって起動に失敗する( [MY-010119] [Server] Aborting

ここまでは良いのだが、8.0.20とそれ以降ではこのAbort処理に失敗して( [ERROR] [MY-013183] [InnoDB] Assertion failure )バックトレースを吐く。

PS C:\Users\yoku0\Downloads\mysql-8.0.30-winx64\mysql-8.0.30-winx64> bin\mysqld --console --skip-grant-tables

2022-08-26T16:11:22.498164Z 0 [System] [MY-010116] [Server] C:\Users\yoku0\Downloads\mysql-8.0.30-winx64\mysql-8.0.30-winx64\bin\mysqld.exe (mysqld 8.0.30) starting as process 20292
2022-08-26T16:11:22.519344Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-08-26T16:11:22.803359Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-08-26T16:11:22.970565Z 0 [Warning] [MY-011311] [Server] Plugin mysqlx reported: 'All I/O interfaces are disabled, X Protocol won't be accessible'
2022-08-26T16:11:23.124791Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-08-26T16:11:23.125007Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2022-08-26T16:11:23.137076Z 0 [System] [MY-010931] [Server] C:\Users\yoku0\Downloads\mysql-8.0.30-winx64\mysql-8.0.30-winx64\bin\mysqld.exe: ready for connections. Version: '8.0.30'  socket: ''  port: 0  MySQL Community Server - GPL.
2022-08-26T16:11:23.137232Z 0 [ERROR] [MY-010131] [Server] TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS
2022-08-26T16:11:23.137332Z 0 [ERROR] [MY-010119] [Server] Aborting
2022-08-26T16:11:25.018791Z 0 [ERROR] [MY-013183] [InnoDB] Assertion failure: trx0sys.cc:643:UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0 thread 8748
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
16:11:25 UTC - mysqld got exception 0x16 ;
Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware.
Thread pointer: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
7ff752740858    mysqld.exe!my_print_stacktrace()[stacktrace.cc:429]
7ff7518de92b    mysqld.exe!print_fatal_signal()[signal_handler.cc:130]
7ff7518de6f3    mysqld.exe!my_server_abort()[signal_handler.cc:241]
7ff7527247fa    mysqld.exe!my_abort()[my_init.cc:263]
7ff75296ca99    mysqld.exe!ut_dbg_assertion_failed()[ut0dbg.cc:99]
7ff752951d0e    mysqld.exe!trx_sys_close()[trx0sys.cc:643]
7ff752903f81    mysqld.exe!srv_shutdown()[srv0start.cc:3240]
7ff75281cb6a    mysqld.exe!innodb_shutdown()[ha_innodb.cc:1603]
7ff7516add5b    mysqld.exe!ha_finalize_handlerton()[handler.cc:726]
7ff7516e9754    mysqld.exe!plugin_deinitialize()[sql_plugin.cc:1121]
7ff7516ef199    mysqld.exe!reap_plugins()[sql_plugin.cc:1190]
7ff7516ede10    mysqld.exe!plugin_shutdown()[sql_plugin.cc:2090]
7ff7516866b9    mysqld.exe!clean_up()[mysqld.cc:2581]
7ff75169aa5a    mysqld.exe!unireg_abort()[mysqld.cc:2444]
7ff75169941f    mysqld.exe!setup_conn_event_handler_threads()[mysqld.cc:3280]
7ff75169d196    mysqld.exe!win_main()[mysqld.cc:8120]
7ff7516954b5    mysqld.exe!mysql_service()[mysqld.cc:8215]
7ff751695adb    mysqld.exe!mysqld_main()[mysqld.cc:8431]
7ff752de4cb4    mysqld.exe!__scrt_common_main_seh()[exe_common.inl:288]
7ffa9f2554e0    KERNEL32.DLL!BaseThreadInitThunk()
7ffa9fee485b    ntdll.dll!RtlUserThreadStart()
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains

明らかにクラッシュはしているものの、直すのは大変だからこのまま(だったらStatusは “Not a Bug” ではなく “Won’t fix” では? とは思うけど)らしいので、この事象にあたった人が焦らないようにこの情報をここに書き残しておきます。

MySQL Bugs: #108304: mysqld.exe crashes --skip-grant-tables without --shared-memory or --named-pipe

skip-grant-tablesしたい時はmy.iniに一緒にshared-memoryを書いてね!


完全な余談。

これ、起動時に起こるクラッシュながら、見えるバックトレースは完全に「終了シーケンスの中でのクラッシュ」なのがちょっと面白かった。Abort処理の中でおかしくなってる(たぶん、InnoDBの初期化が終わってないのにInnoDBの終了処理をしているのがいけない)から終了シーケンスの中でのクラッシュなんだけど、逆にそれが「起動時…だよね…?」とバックトレースに目を取られて [MY-010131] [Server] TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS を見落とさないように注意。

2022/08/25

PKの無いテーブルに、後からAUTO_INCREMENT PRIMARY KEYなカラムを足すときの罠


TL;DR

  • InnoDBの暗黙の行IDはテーブルにINSERTした順番で払い出される

  • ソースでは並列で走ると、INSERTした順番がCOMMITした順番とは限らない

  • レプリカではMulti Thread Applierを使っていない限り、COMMITした順番にINSERTがされる

  • よってソースとレプリカでは暗黙の行IDがズレることがある

  • 【2022/08/25 12:01】書き込みロックをとっても(テーブルを読み書き一切できない時間があって)良いなら多少安全にやる方法はある


百聞は一見に如かず。再現方法。


### on Source, connection 1

master [localhost] {msandbox} ((none)) > CREATE DATABASE d1;

Query OK, 1 row affected (0.00 sec)

master [localhost] {msandbox} ((none)) > CREATE TABLE d1.t1(num int);

Query OK, 0 rows affected (0.02 sec)

master [localhost] {msandbox} ((none)) > BEGIN;

Query OK, 0 rows affected (0.00 sec)

master [localhost] {msandbox} ((none)) > INSERT INTO d1.t1 VALUES (1);

Query OK, 1 row affected (0.03 sec)

### まだCOMMITしない

connection1でINSERTをした後に、connection2で先にCOMMIT

### on Source, connection 2
master [localhost] {msandbox} ((none)) > BEGIN;
Query OK, 0 rows affected (0.00 sec)

master [localhost] {msandbox} ((none)) > INSERT INTO d1.t1 VALUES (2);
Query OK, 1 row affected (0.00 sec)

master [localhost] {msandbox} ((none)) > COMMIT;
Query OK, 0 rows affected (0.00 sec)

で、connection1でCOMMIT

master [localhost] {msandbox} ((none)) > COMMIT;
Query OK, 0 rows affected (0.00 sec)

こうすると、ソースではINSERTした順番が num = 1, num = 2の順番だけど、コミットされた順番が num = 2, num = 1の順番なのでレプリカでINSERTが走るのは num = 2, num = 1の順になる。

よって、PKもないので暗黙の行IDがズレて、ORDER BY無しのSELECTで比較するとこんな感じになる。

$ ./use_all -e "SELECT * FROM d1.t1"
# master
num
1
2
# server: 1:
num
2
1

ここで、ALTER TABLEでAUTO_INCREMENTなPKを足すじゃろ?

master [localhost] {msandbox} ((none)) > ALTER TABLE d1.t1 ADD id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

AUTO_INCREMENTの値はその時の暗黙の行IDの順番に依存して振られていくので、ソースとレプリカでズレる。

$ ./use_all -e "SELECT * FROM d1.t1"
# master
num     id
1       1
2       2
# server: 1:
num     id
2       1
1       2

当然、この状態で DELETE FROM d1.t1 WHERE id = 2 なんてやるともう取り返しがつかない。numが数字だからわかりにくいけど、emailとかだともう致命的にダメだってことが想像できる。

master [localhost] {msandbox} ((none)) > DELETE FROM d1.t1 WHERE id = 2;
Query OK, 1 row affected (0.00 sec)

$ ./use_all -e "SELECT * FROM d1.t1"
# master
num     id
1       1
# server: 1:
num     id
2       1

レプリケーションとしては正常(ALTER TABLEはステートメント形式で伝達されてそれぞれのノードで再計算されるし、 id = 2は行ベースレプリケーションでもPKしか比較しないのでそれぞれでid = 2の行が消える)なので、気を付けないとこのデータ不整合に気が付けない。

$ ./check_slaves
master
port: 25038
             File: mysql-bin.000001
         Position: 6184
Executed_Gtid_Set:
slave # 1
port: 25039
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 6184
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
          Exec_Master_Log_Pos: 6184
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:

俺も同僚から教えてもらったんですが、 MySQL Bugs: #108229: Exists gaps when add a auto_increment column の原因ってこれじゃないかなと思います。まる。


【2022/08/25 12:01】

限りなくユニークに近いカラムがあって、LOCK TABLE WRITE (= ほかのスレッドは読み書きできない)を取っても良いなら、多少安全にやる方法はある。

master [localhost] {msandbox} ((none)) > LOCK TABLE d1.t1 WRITE;
Query OK, 0 rows affected (0.00 sec)

master [localhost] {msandbox} ((none)) > ALTER TABLE d1.t1 ORDER BY num;  ### numが限りなくユニークに近いことが必要だけれども
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

master [localhost] {msandbox} ((none)) > ALTER TABLE d1.t1 ADD id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

master [localhost] {msandbox} ((none)) > UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)


$ ./use_all -e "SELECT * FROM d1.t1"
# master
num     id
1       1
2       2
# server: 1:
num     id
1       1
2       2


2022/08/22

replica_parallel_workers > 1 && replica_preserve_commit_order=ON && slave_parallel_type = LOGICAL_CLOCK && FLUSH PRIVILEGES + アカウント権限周りのステートメントをほぼ同時に打つとMySQLがデッドロックすることがある

TL;DR


再現方法。

8.0.19でレプリケーション設定をしたMySQLを用意する(8.0.28では再現しなかった。5.7.39でも今のところ再現していない)


$ make_replication_sandbox --how_many_slaves=1 8.0.19

$ cd sandboxes/rsandbox_8_0_19/

$ vim master/my.sandbox.cnf

..

binlog_group_commit_sync_delay = 1000000  ### binlogのgroup_commitを起こしやすくするため

$ vim node1/my.sandbox.cnf

..

slave_parallel_workers = 2

slave_preserve_commit_order = ON

slave_parallel_type = LOGICAL_CLOCK

$ ./restart_all

俺は未だにMySQL::Sandboxを使っているのだ、すまんな…。

2つのターミナルを用意して、↓の2ステートメントを1秒以内( binlog_group_commit_sync_delay を100万マイクロ秒に設定しているので、1秒なら同じグループコミットに入れる)に実行する

### Terminal1
$ ./m -e "FLUSH PRIVILEGES"

### Terminal2
$ ./m -e "CREATE USER yoku0825"

体感、50%くらいで再現する。
再現すると、ソースは無事だけどレプリカに一切合切ログインできなくなる。

$ ./s1  ### 刺さって返ってこなくなる

新規接続は全部デッドロックに巻き込まれて動けなくなるけれど、既にログインしているアカウントなら動ける(ただし USE mysql とかすると噛まれて動けなくなる)

SHOW PROCESSLISTで見ると、 FLUSH PRIVILEGESWaiting for table metadata lock で止まり、そのMDLをもってそうなDROP USERは Waiting for preceding transaction to commit で待っている。

あとから追いかけてきたコネクションは Waiting for acl cache lock で待たされている。

slave1 [localhost] {msandbox} ((none)) > SHOW PROCESSLIST;
+----+----------------------+-----------------+------+---------+------+--------------------------------------------------------+--------------------+
| Id | User                 | Host            | db   | Command | Time | State                                                  | Info               |
+----+----------------------+-----------------+------+---------+------+--------------------------------------------------------+--------------------+
|  4 | system user          |                 | NULL | Query   |   95 | Slave has read all relay log; waiting for more updates | NULL               |
|  5 | event_scheduler      | localhost       | NULL | Daemon  |  186 | Waiting on empty queue                                 | NULL               |
|  8 | system user          |                 |      | Connect |   96 | Waiting for table metadata lock                        | FLUSH PRIVILEGES   |
|  9 | system user          |                 |      | Connect |   95 | Waiting for preceding transaction to commit            | DROP USER yoku0825 |
| 10 | system user          | connecting host | NULL | Connect |  186 | Waiting for master to send event                       | NULL               |
| 15 | msandbox             | localhost       | NULL | Query   |    0 | starting                                               | SHOW PROCESSLIST   |
| 16 | unauthenticated user | localhost       | NULL | Connect |   92 | Waiting for acl cache lock                             | NULL               |
+----+----------------------+-----------------+------+---------+------+--------------------------------------------------------+--------------------+
7 rows in set (0.03 sec)
  1. FLUSH PRIVILEGES, DROP USER の順番でソースのbinlogに入る
  2. FLUSH PRIVILEGES, DROP USER の順番でレプリカのrelaylogに入る
  3. last_committed=6 (同じLOGICAL_CLOCK)の枠の中にあるので、コイツらはパラレルで動かされる
  4. DROP USER が先に終わってしまうと、 slave_preserve_commit_order のために FLUSH PRIVILEGES が終わるのを( mysql.user とかの排他メタデータロックを持ったまま) 待つ
  5. FLUSH PRIVILEGESACL_Cache (= mysql.user とかの情報をメモリ上にロードしているアレ) の排他ロックをかけたまま、 mysql.user とかの共有メタデータロックが欲しいので待つ (デッドロック!)
  6. それ以降の接続や権限の読みなおし要求は全て ACL_Cache の排他ロックに阻まれてブロックされる
  7. 死!
slave1 [localhost] {msandbox} (mysql) > SELECT * FROM performance_schema.metadata_locks;
+-------------------+--------------------+------------------+-----------------------+-----------------------+----------------------+---------------+-------------+------------------------+-----------------+----------------+
| OBJECT_TYPE       | OBJECT_SCHEMA      | OBJECT_NAME      | COLUMN_NAME           | OBJECT_INSTANCE_BEGIN | LOCK_TYPE            | LOCK_DURATION | LOCK_STATUS | SOURCE                 | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------------+--------------------+------------------+-----------------------+-----------------------+----------------------+---------------+-------------+------------------------+-----------------+----------------+
| GLOBAL            | NULL               | NULL             | NULL                  |       140468113535472 | INTENTION_EXCLUSIVE  | STATEMENT     | GRANTED     | sql_base.cc:5398       |              48 |             15 |
| BACKUP LOCK       | NULL               | NULL             | NULL                  |       140468113913600 | INTENTION_EXCLUSIVE  | TRANSACTION   | GRANTED     | sql_base.cc:5405       |              48 |             15 |
| SCHEMA            | mysql              | NULL             | NULL                  |       140468113563696 | INTENTION_EXCLUSIVE  | TRANSACTION   | GRANTED     | sql_base.cc:5385       |              48 |             15 |
| TABLE             | mysql              | columns_priv     | NULL                  |       140468113536896 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | db               | NULL                  |       140468113982576 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | columns_priv     | NULL                  |       140468181071040 | SHARED_READ_ONLY     | TRANSACTION   | PENDING     | table.h:2553           |              47 |             39 |
| TABLE             | mysql              | default_roles    | NULL                  |       140468113772864 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | global_grants    | NULL                  |       140468113772960 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | password_history | NULL                  |       140468113540192 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | procs_priv       | NULL                  |       140468113540288 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | proxies_priv     | NULL                  |       140468113540384 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | role_edges       | NULL                  |       140468113534816 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | tables_priv      | NULL                  |       140468113534912 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLE             | mysql              | user             | NULL                  |       140468113535008 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | table.h:2553           |              48 |             15 |
| TABLESPACE        | NULL               | mysql            | NULL                  |       140468113897264 | INTENTION_EXCLUSIVE  | TRANSACTION   | GRANTED     | lock.cc:795            |              48 |             15 |
| ACL CACHE         | NULL               | NULL             | NULL                  |       140468113911328 | EXCLUSIVE            | EXPLICIT      | GRANTED     | sql_auth_cache.cc:3393 |              48 |             16 |
| COMMIT            | NULL               | NULL             | NULL                  |       140468113899824 | INTENTION_EXCLUSIVE  | EXPLICIT      | GRANTED     | handler.cc:1719        |              48 |             16 |
| ACL CACHE         | NULL               | NULL             | NULL                  |       140468448997264 | SHARED               | EXPLICIT      | PENDING     | sql_auth_cache.cc:3393 |              57 |              1 |

バイナリログを開くと、 last_committed が同じになっている。
ただ、これでも先に DROP USER が処理されないと再現はしないので、100%再現とまではいかなかった。

#220822 14:39:48 server id 1  end_log_pos 1411 CRC32 0x3c26f86e         Anonymous_GTID  last_committed=6        sequence_number=7       rbr_only=no     original_committed_timestamp=1661146788679412   immediate_commit_timestamp=1661146788679412     transaction_length=167
# original_commit_timestamp=1661146788679412 (2022-08-22 14:39:48.679412 JST)
# immediate_commit_timestamp=1661146788679412 (2022-08-22 14:39:48.679412 JST)
/*!80001 SET @@session.original_commit_timestamp=1661146788679412*//*!*/;
/*!80014 SET @@session.original_server_version=80019*//*!*/;
/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1411
#220822 14:39:48 server id 1  end_log_pos 1501 CRC32 0xd17997a8         Query   thread_id=15    exec_time=0     error_code=0
SET TIMESTAMP=1661146788/*!*/;
FLUSH PRIVILEGES
/*!*/;

# at 1501
#220822 14:39:49 server id 1  end_log_pos 1578 CRC32 0x91c06a81         Anonymous_GTID  last_committed=6        sequence_number=8       rbr_only=no     original_committed_timestamp=1661146789250989   immediate_commit_timestamp=1661146789250989     transaction_length=178
# original_commit_timestamp=1661146789250989 (2022-08-22 14:39:49.250989 JST)
# immediate_commit_timestamp=1661146789250989 (2022-08-22 14:39:49.250989 JST)
/*!80001 SET @@session.original_commit_timestamp=1661146789250989*//*!*/;
/*!80014 SET @@session.original_server_version=80019*//*!*/;
/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1578
#220822 14:39:49 server id 1  end_log_pos 1679 CRC32 0xf4243118         Query   thread_id=16    exec_time=0     error_code=0    Xid = 34
SET TIMESTAMP=1661146789/*!*/;
DROP USER yoku0825
/*!*/;

InnoDBとかで刺さる時と違って、CPU使用率も大して上がらずに緩やかに刺さった。
対処方法は kill -9 での再起動(もう kill -15mysqladmin shutdown では落ちてくれない)

gtid_mode=ONになってないとMTS中の異常終了で起動した後もSQL_Threadが止まったり(これはもうgtid_mode=ONの時以外MTSは危険…)、そもそも起動の時にまた同じ組み合わせをパラレル適用しようとしてまた刺さったり(replica_parallel_workers = 1にして起動して回避する)とか、なかなかエグい。

いつかぶち当たる人がいたら、参考にしてください…。
(バージョンアップすれば当たらなくなりそうだからバージョン上げましょう…)