GA

2024/09/02

MySQLだけでファイルシステムフルやMySQLだけでファイルシステムハングを再現するアイディア

TL;DR

  • 障害時の動作を確認するためにファイルシステムをフルにしたり xfs_freeze をかけたいことはままある
  • が、MySQLの動作パーティションが分かれていない場合、本当にやると調査用のシェルまで動けなくなってしまう
  • ループバックデバイスを使ってdatadirだけ起こすのが楽

↑だけで全部言い尽くしてしまった。
取り敢えずdatadirに割り当てる好きなサイズのファイルを切り出す。

[yoku0825@yoku0825-conoha work]$ dd if=/dev/zero of=./datadir bs=1M count=300
300+0 records in
300+0 records out
314572800 bytes (315 MB) copied, 0.26401 s, 1.2 GB/s

[yoku0825@yoku0825-conoha work]$ ll -h
total 301M
-rw-r--r-- 1 yoku0825 yoku0825 300M Sep  2 13:20 datadir

ファイルシステムを作ってから好きなマウントディレクトリに割り当てる。

[yoku0825@yoku0825-conoha work]$ mkfs -t xfs ./datadir
meta-data=./datadir              isize=512    agcount=4, agsize=19200 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=76800, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=855, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

[yoku0825@yoku0825-conoha work]$ sudo mount ./datadir /mnt

[yoku0825@yoku0825-conoha work]$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop1      297M   16M  282M   6% /mnt

既存のdatadirの中身を /mnt に移してシンボリックリンクにするなり、 --datadir=/mnt--initialize するなり、 ラジバンダリ
俺は yoku0825 というOSアカウントで mysqld を起動するので、オーナーを変えてしまっている。

[yoku0825@yoku0825-conoha work]$ sudo chown -R yoku0825. /mnt

[yoku0825@yoku0825-conoha work]$ /usr/mysql/8.4.2/bin/mysqld --no-defaults --datadir=/mnt --initialize-insecure
2024-09-02T04:21:51.223351Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
2024-09-02T04:21:51.223497Z 0 [Warning] [MY-010139] [Server] Changed limits: max_open_files: 1024 (requested 8161)
2024-09-02T04:21:51.223507Z 0 [Warning] [MY-010142] [Server] Changed limits: table_open_cache: 431 (requested 4000)
2024-09-02T04:21:51.225861Z 0 [System] [MY-013169] [Server] /usr/mysql/8.4.2/bin/mysqld (mysqld 8.4.2) initializing of server in progress as process 22201
2024-09-02T04:21:51.235592Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-09-02T04:21:51.565478Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-09-02T04:21:52.610123Z 5 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
2024-09-02T04:21:55.333522Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end.

[yoku0825@yoku0825-conoha work]$ /usr/mysql/8.4.2/bin/mysqld --no-defaults --datadir=/mnt --daemonize          
mysqld will log errors to /mnt/yoku0825-conoha.err
mysqld is running as pid 22300

テキトーにbinlogを吐きそうな何かをしてやると

[yoku0825@yoku0825-conoha work]$ mysqlslap -S /tmp/mysql.sock -uroot --auto-generate-sql --auto-generate-sql-execute-number=10000000 --auto-generate-sql-load-type=w -c 10

[yoku0825@yoku0825-conoha work]$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop1      297M  297M   20K 100% /mnt

[yoku0825@yoku0825-conoha work]$ tail /mnt/yoku0825-conoha.err 
2024-09-02T04:22:12.892895Z 0 [Warning] [MY-010139] [Server] Changed limits: max_open_files: 1024 (requested 8161)
2024-09-02T04:22:12.892905Z 0 [Warning] [MY-010142] [Server] Changed limits: table_open_cache: 431 (requested 4000)
2024-09-02T04:22:13.150060Z 0 [System] [MY-010116] [Server] /usr/mysql/8.4.2/bin/mysqld (mysqld 8.4.2) starting as process 22298
2024-09-02T04:22:13.177164Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-09-02T04:22:13.436646Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-09-02T04:22:13.796358Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2024-09-02T04:22:13.796400Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2024-09-02T04:22:13.821037Z 0 [System] [MY-010931] [Server] /usr/mysql/8.4.2/bin/mysqld: ready for connections. Version: '8.4.2'  socket: '/tmp/mysql.sock'  port: 3306  Source distribution.
2024-09-02T04:22:13.821757Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /tmp/mysqlx.sock
2024-09-02T04:26:29.994586Z 27 [ERROR] [MY-000035] [Server] Disk is full writing './binlog.000001' (OS errno 28 - No space left on device). Waiting for someone to free space... Retry in 60 secs. Message reprinted in 600 secs.     <--- これ
[yoku0825@yoku0825-conoha work]$ mysql -S /tmp/mysql.sock -uroot                                             
mysql> SHOW PROCESSLIST;
+----+-----------------+-----------+-----------+---------+------+----------------------------+------------------------------------------------------------------------------------------------------+
| Id | User            | Host      | db        | Command | Time | State                      | Info                                                                                                 |
+----+-----------------+-----------+-----------+---------+------+----------------------------+------------------------------------------------------------------------------------------------------+
|  5 | event_scheduler | localhost | NULL      | Daemon  |  341 | Waiting on empty queue     | NULL                                                                                                 |
| 19 | root            | localhost | mysqlslap | Sleep   |  115 |                            | NULL                                                                                                 |
| 20 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (1665728802,'8qB5MAR1caTvNFXB00HKShGa1uToGCMP2ZMHjpABFg6fnTioTz8pZGNQAkEJwckr9 |
| 21 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (866596855,'naQuzhMt1IrZIJMkbLAKBNNKKK2sCknzI5uHeGAgQuDd5SLgpN0smODyc7qorTo1Qa |
| 22 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (100669,'qnMdipW5KkXdTjGCh2PNzLoeR0527frpQDQ8uw67Ydk1K06uuNHtkxYBxT5w8plb2Bbpz |
| 23 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (1137990260,'pvYr3YntZ2DoGrwWfL91bW9Epw8iO6vDuR4xrkqOe3Dum1PPEQQpwRvmO3Kg2Ftob |
| 24 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (2010720737,'iLEkea9eOuLJweKJjQ3IJlW1dXTSs6dbJjJpHTRZFgkBJ4XuNQ4iCRchy51r3WQEE |
| 25 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (866596855,'naQuzhMt1IrZIJMkbLAKBNNKKK2sCknzI5uHeGAgQuDd5SLgpN0smODyc7qorTo1Qa |
| 26 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (100669,'qnMdipW5KkXdTjGCh2PNzLoeR0527frpQDQ8uw67Ydk1K06uuNHtkxYBxT5w8plb2Bbpz |
| 27 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (1759592334,'3lkoxjtvgLu5xKHSTTtJuGE5F5QqmCcppCTmvFZScRZQgim93gSxwb24gKmIPEzEQ |
| 28 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (866596855,'naQuzhMt1IrZIJMkbLAKBNNKKK2sCknzI5uHeGAgQuDd5SLgpN0smODyc7qorTo1Qa |
| 29 | root            | localhost | mysqlslap | Query   |   85 | waiting for handler commit | INSERT INTO t1 VALUES (1759592334,'3lkoxjtvgLu5xKHSTTtJuGE5F5QqmCcppCTmvFZScRZQgim93gSxwb24gKmIPEzEQ |
| 30 | root            | localhost | NULL      | Query   |    0 | init                       | SHOW PROCESSLIST                                                                                     |
+----+-----------------+-----------+-----------+---------+------+----------------------------+------------------------------------------------------------------------------------------------------+
13 rows in set, 1 warning (0.01 sec)

とまあファイルシステムが埋まるとbinlogが吐けなくて waiting for handler commit で突き刺さることがわかります。

mysql コマンドラインクライアントでの新規接続には成功するけど SHOW BINARY LOGS が刺さったり (binlogを参照するためのmutexが競合する)、 performance_schema.processlist は読み取れる (MySQL 8.4の SHOW PROCESSLIST はこれを読む)けど information_schema.processlist は読めない (テンポラリーテーブルを作るので失敗した)とか

mysql> SELECT * FROM information_schema.processlist;
ERROR 1114 (HY000): The table '/tmp/#sql571c_22_0' is full

mysql> SELECT * FROM performance_schema.processlist;                                                                       
..
14 rows in set (0.04 sec)

SHUTDOWN ステートメントは刺さるかなと思ったら刺さらずにちゃんと停止したり、 binlog_error_action はファイルシステムフルではトリガーされないのだなあと思ったり、学びはあると思います

2024/09/01

21年の時を経てMySQL 3.23がCentOS7.9にインストールされるはなし

TL;DR


日本MySQLユーザ会会(MyNA会) 2024年8月オフライン! LTSが出たぞ祭り に行ってきました。

本編(?)、幕間(?)、LTと3回も登場してしまってすいません。

LT大会を企画していたけどその前のご歓談タイムにもプロジェクタとマイクを勝手に使って話してる人がいて、

これはその、みんながピザを食べ始めた時に「歓談タイムの間、プロジェクター空いてるなら借りますね!」って勝手に始めた幕間の話です。

もともとやろうとしていたことは、

ずっとMySQLをビルドし続けている自慢(?)のConoHa の環境をお目にかけようと思っていただけなんですが、

[yoku0825@yoku0825-conoha ~]$ ll /usr/mysql
total 32
drwxr-xr-x 10 yoku0825 yoku0825 4096 Jun 18  2021 5.0.96
drwxr-xr-x 11 yoku0825 yoku0825 4096 May  2  2021 5.1.73
drwxr-xr-x 13 yoku0825 yoku0825 4096 May  1 15:37 5.5.62
drwxr-xr-x 13 yoku0825 yoku0825 4096 Sep 15  2021 5.6.51
drwxr-xr-x 11 yoku0825 yoku0825 4096 Jun  4 15:21 5.7.44
drwxrwxr-x 13 yoku0825 yoku0825 4096 Aug 31 22:10 8.0.39
drwxrwxr-x 13 yoku0825 yoku0825 4096 Aug 20 15:43 8.4.2
drwxrwxr-x 13 yoku0825 yoku0825 4096 Jul 25 09:29 9.0.1

おれ「どれでも好きなものを起動しますよ?」
??「あれ、4.0は?」
「やってみますか」
「マジか」

みたいなノリで始まりました。

古いMySQLのバイナリが欲しいとなると頼りになるのは SH2さんMySQL Archives - dbstudy.info

アクセスしてみたら3.23のバイナリまであったので、「折角なら3.23にしましょうか」みたいな感じでスタート。

素直にコンパイルできる自信は無いので、バイナリが欲しくてrpmパッケージを使う。

[yoku0825@yoku0825-conoha ~]$ sudo yum install https://dbstudy.info/mysqlarchives/3.23.58/generic/MySQL-3.23.58-1.i386.rpm
Loaded plugins: auto-update-debuginfo, fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager

This system is not registered with an entitlement server. You can use subscription-manager to register.

MySQL-3.23.58-1.i386.rpm                                                                                 | 8.2 MB  00:00:00     
Examining /var/tmp/yum-root-lpP0lC/MySQL-3.23.58-1.i386.rpm: MySQL-3.23.58-1.i386
Marking /var/tmp/yum-root-lpP0lC/MySQL-3.23.58-1.i386.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package MySQL.i386 0:3.23.58-1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================================================================
 Package                  Arch                    Version                        Repository                                Size
================================================================================================================================
Installing:
 MySQL                    i386                    3.23.58-1                      /MySQL-3.23.58-1.i386                     22 M

Transaction Summary
================================================================================================================================
Install  1 Package

Total size: 22 M
Installed size: 22 M
Is this ok [y/d/N]: y
..

当日ログ取ってなかったなあと思ってもう1回ログを作ろうとしたら、案外一発で入ってしまった。
取り敢えず mysqld を起動してみる。

[yoku0825@yoku0825-conoha ~]$ /usr/sbin/mysqld --no-defaults
/usr/sbin/mysqld: Can't change dir to '/var/lib/mysql/' (Errcode: 13)
240901 18:23:44  Aborting

240901 18:23:44  /usr/sbin/mysqld: Shutdown Complete

/var/lib/mysql が書ける状態になってない。

[yoku0825@yoku0825-conoha ~]$ sudo rm -r /var/lib/mysql
[yoku0825@yoku0825-conoha ~]$ sudo mkdir /var/lib/mysql
[yoku0825@yoku0825-conoha ~]$ sudo chown yoku0825. /var/lib/mysql
[yoku0825@yoku0825-conoha ~]$ /usr/sbin/mysqld --no-defaults
240901 21:35:00  /usr/sbin/mysqld: Table 'mysql.host' doesn't exist

ああ、datadir初期化してなかった。この時代(?) はまだ mysql_install_db だったのはわかる。

[yoku0825@yoku0825-conoha ~]$ /usr/bin/mysql_install_db --no-defaults
Sorry, the host 'yoku0825-conoha' could not be looked up.
Please configure the 'hostname' command to return a correct hostname.
If you want to solve this at a later stage, restart this script with
the --force option

ああ、あった、 /etc/hosts なりで自分自身のホスト名を名前解決できないといけなかったやつ(インストール後にホスト名を変えてるとこうなる)

今回は特に困らないので --force で続行。

[yoku0825@yoku0825-conoha ~]$ /usr/bin/mysql_install_db --no-defaults --force
Preparing db table
Preparing host table
Preparing user table
Preparing func table
Preparing tables_priv table
Preparing columns_priv table
Installing all prepared tables
240901 21:37:34  /usr/sbin/mysqld: Shutdown Complete

To start mysqld at boot time you have to copy support-files/mysql.server
to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
This is done with:
/usr/bin/mysqladmin -u root  password 'new-password'
/usr/bin/mysqladmin -u root -h yoku0825-conoha  password 'new-password'
See the manual for more instructions.

You can start the MySQL daemon with:
cd / ; /usr/bin/safe_mysqld &

You can test the MySQL daemon with the benchmarks in the 'sql-bench' directory:
cd sql-bench ; run-all-tests

Please report any problems with the /usr/bin/mysqlbug script!

The latest information about MySQL is available on the web at
http://www.mysql.com
Support MySQL by buying support/licenses at https://order.mysql.com

rootのパスワードを設定しろよ、という当時お決まりの文句と、 mysqld_safe ではなく safe_mysqld (俺はこの時代を知らない!!) で起動しろということを言われる。

まあ気にせず mysqld で直接起動する。

[yoku0825@yoku0825-conoha ~]$ /usr/sbin/mysqld --no-defaults
/usr/sbin/mysqld: ready for connections

なんともあっさりした出力…。
フォアグラウンドで起動するので別のターミナルからアクセスする。

ソケットファイルの場所がわからないので lsof からたどる。

[yoku0825@yoku0825-conoha ~]$ ps auxwww | grep mysqld
yoku0825  1820  0.0  0.0  10696   836 pts/1    S+   21:40   0:00 /usr/sbin/mysqld --no-defaults
yoku0825  1821  0.0  0.0  10696   836 pts/1    S+   21:40   0:00 /usr/sbin/mysqld --no-defaults
yoku0825  1822  0.0  0.0  10696   836 pts/1    S+   21:40   0:00 /usr/sbin/mysqld --no-defaults
yoku0825  1950  0.0  0.0   9092   680 pts/2    S+   21:41   0:00 grep --color=auto mysqld

わーまだマルチスレッドじゃなくてマルチプロセスの頃だ!!!

[yoku0825@yoku0825-conoha ~]$ ps -elf | grep mysqld
0 S yoku0825  1820  1369  0  80   0 -  2674 poll_s 21:40 pts/1    00:00:00 /usr/sbin/mysqld --no-defaults
1 S yoku0825  1821  1820  0  80   0 -  2674 poll_s 21:40 pts/1    00:00:00 /usr/sbin/mysqld --no-defaults
1 S yoku0825  1822  1821  0  80   0 -  2674 sigsus 21:40 pts/1    00:00:00 /usr/sbin/mysqld --no-defaults
0 S yoku0825  2127  1833  0  80   0 -  2273 pipe_w 21:42 pts/2    00:00:00 grep --color=auto mysqld
[yoku0825@yoku0825-conoha ~]$ lsof -p 1820
COMMAND  PID     USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
mysqld  1820 yoku0825  cwd    DIR              253,2     4096  286555 /var/lib/mysql
mysqld  1820 yoku0825  rtd    DIR              253,2     4096       2 /
mysqld  1820 yoku0825  txt    REG              253,2  2110756  691929 /usr/sbin/mysqld
mysqld  1820 yoku0825    0u   CHR              136,1      0t0       4 /dev/pts/1
mysqld  1820 yoku0825    1u   CHR              136,1      0t0       4 /dev/pts/1
mysqld  1820 yoku0825    2u   CHR              136,1      0t0       4 /dev/pts/1
mysqld  1820 yoku0825    3u  IPv4            4401525      0t0     TCP *:mysql (LISTEN)
mysqld  1820 yoku0825    4u  unix 0x0000000000000000      0t0 4401526 /var/lib/mysql/mysql.sock
mysqld  1820 yoku0825    5r  FIFO                0,9      0t0 4401527 pipe
mysqld  1820 yoku0825    6w  FIFO                0,9      0t0 4401527 pipe

ソケットファイルは /var/lib/mysql/mysql.sock である、OK。

[yoku0825@yoku0825-conoha ~]$ mysql -uroot -S /var/lib/mysql/mysql.sock
ERROR 2027 (HY000): Malformed packet

ああ、これ mysql コマンドラインクライアントと mysqld の互換性がない時に出る決まり文句だ。

[yoku0825@yoku0825-conoha ~]$ mysql --version
mysql  Ver 8.0.39 for Linux on x86_64 (Source distribution)

mysql コマンドラインクライアントのバージョンが8.0だったから。5.0の mysql コマンドラインクライアントならつなげるかな。

[yoku0825@yoku0825-conoha ~]$ /usr/mysql/5.0.96/bin/mysql -uroot -S /var/lib/mysql/mysql.sock
Warning: /usr/mysql/5.0.96/bin/mysql: unknown variable 'loose-binary-as-hex=0'
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 3.23.58

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

いけた。

mysql> SELECT @@version, NOW();
+-----------+---------------------+
| @@VERSION | NOW()               |
+-----------+---------------------+
| 3.23.58   | 2024-09-01 21:46:57 | 
+-----------+---------------------+
1 row in set (0.00 sec)

当日はrpmインストールした時に俺の秘伝の(?) /etc/my.cnf が消失して他のバージョンを起動できなくなったりとかしたけれど、今回はすんなりいってしまった。

令和6年にもなってMySQL 3.23が使いたくなった時の(?) 参考までに。

2024/08/27

ALTER TABLE .. Engine = InnoDBとOPTIMIZE TABLEは結局どう違うのか

TL;DR

  • ステートメントの権限評価が違う。 ALTER TABLEGRANT ALTER が必要だが、 OPTIMIZE TABLEGRANT SELECT, INSERT だけで成立する
  • innodb_optimize_fulltext_only をONにしていない限りはどっちでもほぼ同じことが起こる
    • ONにしている場合は違うことが起こる。後述。
  • OPTIMIZE TABLE には OPTIMIZE LOCAL TABLE または OPTIMIZE NO_WRITE_TO_BINLOG TABLE 構文があり、これは ALTER TABLE には存在しない機能
    • 普段から OPTIMIZE LOCAL TABLE を使っている人にだけ伝われば。初めて聞いた人にはきっと関係ないので忘れて良い

同じことが起こる仕組み。

OPTIMIZE TABLESql_cmd_optimize_table::execute から mysql_admin_table を通って table->table->file->*operator_func つまり ha_innobase::optimize に到達する。

ha_innobase::optimizeinnodb_optimize_fulltext_only がセットされているかを判定して、ONの場合は fts_sync_tablefts_optimize_table を呼び出す。OFFの場合は何もせずに HA_ADMIN_TRY_ALTER を返す。

返された HA_ADMIN_TRY_ALTERmysql_admin_table でハンドルされて、おなじみの Table does not support optimize, doing recreate + analyze instead のメッセージを書き出しながら mysql_recreate_table に突入する。 mysql_recreate_tablemysql_alter_table を呼び出す。

それに対して ALTER TABLESql_cmd_alter_table::execute から 直接(?) mysql_alter_table に突入する。

どちらも最終的には(ALGORITHM= COPYとかしていない限り) ha_innobase::inplace_alter_table にたどり着く。

OPTIMIZE TABLE から入るとこう。

(gdb) bt
+bt
#0  ha_innobase::inplace_alter_table(TABLE*, Alter_inplace_info*, dd::Table const*, dd::Table*) () at /home/yoku0825/mysql-8.4.2/storage/innobase/handler/handler0alter.cc:1560
#1  0x0000000000f675c2 in ha_inplace_alter_table (new_table_def=0x7f9b80c2e420, old_table_def=0x7f9b80052f50, ha_alter_info=0x7f9bc0686800, altered_table=0x7f9b80dabee0, this=<optimized out>)
    at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:13740
#2  mysql_inplace_alter_table(THD*, dd::Schema const&, dd::Schema const&, dd::Table const*, dd::Table*, Table_ref*, TABLE*, TABLE*, Alter_inplace_info*, enum_alter_inplace_result, Alter_table_ctx*, std::set<std::string, std::less<std::string>, Stateless_allocator<std::string, histograms::Histogram_psi_key_alloc, My_free_functor> >&, FOREIGN_KEY*, unsigned int, Foreign_key_parents_invalidator*) ()
    at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:13801
#3  0x0000000000f7e07f in mysql_alter_table(THD*, char const*, char const*, HA_CREATE_INFO*, Table_ref*, Alter_info*) () at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:17675
#4  0x0000000000f83158 in mysql_recreate_table(THD*, Table_ref*, bool) () at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:18915
#5  0x00000000013df51a in mysql_admin_table(THD*, Table_ref*, HA_CHECK_OPT*, char const*, thr_lock_type, bool, bool, unsigned int, int (*)(THD*, Table_ref*, HA_CHECK_OPT*), int (handler::*)(THD*, HA_CHECK_OPT*), int, Alter_info*, bool) [clone .constprop.0] () at /home/yoku0825/mysql-8.4.2/sql/sql_admin.cc:1327
#6  0x00000000013e0ab2 in Sql_cmd_optimize_table::execute (this=0x7f9b80dae8e8, thd=0x7f9b80006bd0) at /home/yoku0825/mysql-8.4.2/sql/sql_admin.cc:1933
#7  0x0000000000ec5c01 in mysql_execute_command(THD*, bool) () at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:4737
#8  0x0000000000ec9cd0 in dispatch_sql_command(THD*, Parser_state*) () at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:5392
#9  0x0000000000ecc741 in dispatch_command(THD*, COM_DATA const*, enum_server_command) () at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:2136
#10 0x0000000000ecd356 in do_command (thd=thd@entry=0x7f9b80006bd0) at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:1465
#11 0x00000000010326d8 in handle_connection (arg=arg@entry=0x83a1150) at /home/yoku0825/mysql-8.4.2/sql/conn_handler/connection_handler_per_thread.cc:304
#12 0x00000000028ae595 in pfs_spawn_thread (arg=0x84e94a0) at /home/yoku0825/mysql-8.4.2/storage/perfschema/pfs.cc:3061
#13 0x00007f9bcf03aea5 in start_thread (arg=0x7f9bc068c700) at pthread_create.c:307
#14 0x00007f9bcd4e8b0d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

ALTER TABLE から入るとこう。

(gdb) bt
+bt
#0  ha_innobase::inplace_alter_table(TABLE*, Alter_inplace_info*, dd::Table const*, dd::Table*) () at /home/yoku0825/mysql-8.4.2/storage/innobase/handler/handler0alter.cc:1560
#1  0x0000000000f675c2 in ha_inplace_alter_table (new_table_def=0x7f9b80cf5b50, old_table_def=0x7f9b80052f50, ha_alter_info=0x7f9bc0686de0, altered_table=0x7f9b80e290e0, this=<optimized out>)
    at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:13740
#2  mysql_inplace_alter_table(THD*, dd::Schema const&, dd::Schema const&, dd::Table const*, dd::Table*, Table_ref*, TABLE*, TABLE*, Alter_inplace_info*, enum_alter_inplace_result, Alter_table_ctx*, std::set<std::string, std::less<std::string>, Stateless_allocator<std::string, histograms::Histogram_psi_key_alloc, My_free_functor> >&, FOREIGN_KEY*, unsigned int, Foreign_key_parents_invalidator*) ()
    at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:13801
#3  0x0000000000f7e07f in mysql_alter_table(THD*, char const*, char const*, HA_CREATE_INFO*, Table_ref*, Alter_info*) () at /home/yoku0825/mysql-8.4.2/sql/sql_table.cc:17675
#4  0x00000000013e5619 in Sql_cmd_alter_table::execute(THD*) () at /home/yoku0825/mysql-8.4.2/sql/sql_alter.cc:350
#5  0x0000000000ec5c01 in mysql_execute_command(THD*, bool) () at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:4737
#6  0x0000000000ec9cd0 in dispatch_sql_command(THD*, Parser_state*) () at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:5392
#7  0x0000000000ecc741 in dispatch_command(THD*, COM_DATA const*, enum_server_command) () at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:2136
#8  0x0000000000ecd356 in do_command (thd=thd@entry=0x7f9b80006bd0) at /home/yoku0825/mysql-8.4.2/sql/sql_parse.cc:1465
#9  0x00000000010326d8 in handle_connection (arg=arg@entry=0x83a1150) at /home/yoku0825/mysql-8.4.2/sql/conn_handler/connection_handler_per_thread.cc:304
#10 0x00000000028ae595 in pfs_spawn_thread (arg=0x84e94a0) at /home/yoku0825/mysql-8.4.2/storage/perfschema/pfs.cc:3061
#11 0x00007f9bcf03aea5 in start_thread (arg=0x7f9bc068c700) at pthread_create.c:307
#12 0x00007f9bcd4e8b0d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

という訳で、

  • ステートメントの権限評価が違う。 ALTER TABLEGRANT ALTER が必要だが、 OPTIMIZE TABLEGRANT SELECT, INSERT だけで成立する
  • innodb_optimize_fulltext_only をONにしていない限りはどっちでもほぼ同じことが起こる
  • OPTIMIZE TABLE には OPTIMIZE LOCAL TABLE または OPTIMIZE NO_WRITE_TO_BINLOG TABLE 構文があり、これは ALTER TABLE には存在しない機能

この3つが気にならなければどっちを使っても一緒です。



【2024/09/02 13:00】

すっかり忘れてたんですけど OPTIMIZE TABLE から入った場合は ANALYZE TABLE  もトリガーされました。

https://github.com/mysql/mysql-server/blob/mysql-8.4.2/sql/sql_admin.cc#L1367

taka_yukiさん ありがとうございます!


ANALYZE TABLE は割と勝手にバックグラウンドでトリガーされるのでやはりそこまで違いを気にしたことはないです)



ta