気づけば3月、今年はコロナウィルスの影響で参加しようと思っていたイベントが中止だったり、僕自身参加を自粛したりしてました。 この状況はいつまで続くんですかね・・・
さて今回は小ネタです。
皆さんはmysqlクライアントのpager機能を使っていますでしょうか?
現在設定されているpagerはstatus
または¥s
を実行することで確認できます。
mysql> status; -------------- mysql Ver 8.0.19 for Linux on x86_64 (Source distribution) Connection id: 9 Current database: Current user: root@localhost SSL: Not in use Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 8.0.19-debug Source distribution Protocol version: 10 Connection: Localhost via UNIX socket Server characterset: utf8mb4 Db characterset: utf8mb4 Client characterset: utf8mb4 Conn. characterset: utf8mb4 UNIX socket: /mysql/MyHome/tmp/mysql.sock Binary data as: Hexadecimal Uptime: 21 hours 57 min 24 sec Threads: 2 Questions: 19 Slow queries: 0 Opens: 157 Flush tables: 3 Open tables: 77 Queries per second avg: 0.000 --------------
Current pager
に現在のpagerが表示されていて、上の例ではstdout
つまり標準出力に設定されていることがわかります。
pagerについては、mysqlクライアントで実行したクエリの結果をパイプで渡す先になるものと考えるとわかりやすいのかなと思います。
例えば後述するless
コマンドをpagerに設定すれば結果をスクロールしながら確認することができます。
mysql> pager less
おそらく最もシンプルで使い勝手がいいのがless
コマンドではないでしょうか。
例えばあるデータベースに含まれているテーブル一覧を表示したいといったときに力を発揮します。データベースによっては含まれるテーブルが数百を超えることも珍しくないと思いますが、デフォルトのpagerだとその一覧が一気に画面に出力されてしまいます。
mysql> show tables from performance_schema; +------------------------------------------------------+ | Tables_in_performance_schema | +------------------------------------------------------+ | accounts | | cond_instances | | data_lock_waits | | data_locks | | events_errors_summary_by_account_by_error | | events_errors_summary_by_host_by_error | | events_errors_summary_by_thread_by_error | | events_errors_summary_by_user_by_error | | events_errors_summary_global_by_error | | events_stages_current | | events_stages_history | . snip
このような場合に下記のようにpagerを設定すると長い一覧をスクロールや検索しながら確認することができます。
mysql> pager less PAGER set to 'less'
またlessのオプションも同時に渡すことができます。
デフォルトだとless
コマンドを終了させると結果が残りませんが、-X
オプションを指定すると結果が残るようになるので便利です。
mysql> pager less -X PAGER set to 'less -X'
less
には豊富なオプションがあるため自分が使いやすいと感じるpagerを設定するとよいでしょう。
なおオプション指定時などpagerに渡す引数が複数になるときはそれらをクォートで囲まないよう注意が必要です。
mysql> pager 'less -X' PAGER set to ''less -X'' mysql> show tables from performance_schema; sh: less -X: コマンドが見つかりません 103 rows in set (0.07 sec)
クォートで囲ったものをpagerに設定すると、それらを1つのコマンドとして認識してしまうため、上記のようにコマンドが見つからないといったエラーが出力されます。(ダブルクォーテーションで囲っても同じ事が起こります)
mysql> pager grep
grep
もまた便利なpagerの一つです。
これを使うとWHERE
句で指定しなくても特定のカラムを含む行のみ表示できたり、逆に特定のキーワードを含む文字列以外を表示できたりします。
僕はたまに下記のようなpagerを設定します。
mysql> pager grep -v Sleep PAGER set to 'grep -v Sleep'
このpager、何が嬉しいかというと例えばなにか特定のクエリが原因でDBが詰まっているような状況でその原因のクエリを特定するのに便利です。
そのような状況では大抵の場合そのクエリを実行しているスレッドが複数存在しています。しかし、何百本も接続がある環境でshow processlist
から確認するのは大変です。障害対応など急いでいるときは特に。
そんなときに上記のpagerを設定してあげるとshow processlist
しただけでSleepになっていないすなわちRunningのスレッドだけ表示することができます。
もちろんinformation_schema.processlist
からWHERE
を駆使して同様の事ができますが、pagerを使うほうが圧倒的に速いはずです。
実際に僕もこれを使って障害対応をした経験があります。 非常におすすめです。
mysql> pager gzip -c > $DIR
これはあまり使う機会は多くないかもしれませんが、pagerの力を感じていただけるものだと思います。
mysql> pager gzip -c > /tmp/output.gz PAGER set to 'gzip -c > /tmp/output.gz' mysql> show tables from performance_schema; 103 rows in set (0.03 sec) mysql> system zcat /tmp/output.gz | head +------------------------------------------------------+ | Tables_in_performance_schema | +------------------------------------------------------+ | accounts | | cond_instances | | data_lock_waits | | data_locks | | events_errors_summary_by_account_by_error | | events_errors_summary_by_host_by_error | | events_errors_summary_by_thread_by_error |
これはSELECTした結果をgzipで圧縮をして/tmp下にoutput.gzという名前でファイルに吐いている様子です。
pagerを使って出力をしているのでSELECT結果以外にも応用が効きます。
例えば障害時点のshow processlist
をとりあえずログとして残しておくといった使い方ができます。
pagerの設定と解除方法
毎回pagerを設定するのは面倒くさいのでよく使うpagerはmy.cnfに記述しておくと良いでしょう。
[mysql] pager="less -n -i -F -X -E -R"
まだ現在のpagerを解除したいときはnopager
コマンドを実行することで解除できます。
mysql> pager grep root PAGER set to 'grep root' mysql> show processlist; | 10 | root | localhost | NULL | Query | 0 | starting | show processlist | 2 rows in set (0.00 sec) mysql> nopager PAGER set to stdout mysql> show processlist; +----+-----------------+-----------+------+---------+-------+------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+-----------+------+---------+-------+------------------------+------------------+ | 4 | event_scheduler | localhost | NULL | Daemon | 90429 | Waiting on empty queue | NULL | | 10 | root | localhost | NULL | Query | 0 | starting | show processlist | +----+-----------------+-----------+------+---------+-------+------------------------+------------------+ 2 rows in set (0.00 sec)
まとめ
今回は小ネタでmysqlクライアントのpagerを見てきました。
pagerにはLinuxコマンドをそのまま渡せるので(もちろんパイプを使ってさらに広げることも可能)可能性は無限大です。
ぜひ便利なpagerを見つけてみてください。