GA

2023/12/07

明日使えない地味なシェルスクリプト用ワンライナー集

この記事は MySQLのカレンダー | Advent Calendar 2023 の7日目の記事です。
6日目は けんつ さんの MySQL いい感じにコントリビュートする方法(非公式) - それが僕には楽しかったんです。 でした。


TL;DR

  • なんの変哲もないよく使うワンライナーです。SQLだけでできたり使ったりするものは入っていない気がする

バージョンxxx移行yyy未満、みたいなのをやりたい

  • MySQLは内部的にも メジャーバージョン番号 * 10000 + マイナーバージョン番号 * 100 + リリース番号 みたいな計算式をよく使っているのでそれに倣う
$ mysql -sse "SELECT @@version" | awk -F"[.-]" '{printf("%d%02d%02d\n", $1, $2, $3)}'
$ mysql -sse "SELECT sys.version_major() * 10000 + sys.version_minor() * 100 + sys.version_patch()"

バイナリログだけのサイズを合計したい

$ mysql -sse "SHOW BYNARY LOGS" | awk '{i += $2}END{print i}' | numfmt --to=iec

(番外)リレーログだけのサイズを合計したい

  • SHOW BINARY LOGS みたいなのが無いので、厳密にやろうとすると大変 ( relay_log_basename をたどったりとか)。おとなしく *relay* で引いちゃうのが良いんではないか。
$ ls -l /path/to/datadir/*relay* | awk '{i += $5}END{print i}' | numfmt --to=iec

master_info_repositoryからCHANGE REPLICATION SOURCE TOステートメントを作る

  • 急に perl が出てくるのは awk だとシングルクォートが面倒だったから
$ mysql -sse "SELECT host, port, user_name, user_password, enabled_auto_position FROM mysql.slave_master_info WHERE channel_name = ''" |  perl -nlaE 'printf(qq{CHANGE REPLICATION SOURCE TO source_host = "%s", source_port = %d, source_user = "%s", source_password = "%s", source_auto_position = %d;\n}, @F)'

(番外) master.infoファイルからCHANGE REPLICATION SOURCE TOステートメントを作る

  • cat で取った内容を一度変数に詰めるとspace seperatedな1行に出来ることを利用している

    • ワンライナーじゃない(∩゚д゚)アーアーきこえなーい
  • master.info の並び順は一応ドキュメントに解説されているけれど、将来変わるかも知れないしそもそも master_info_repository=FILE 自体が非推奨になったので微妙。

$ line=$(cat master.info)
$ echo $line | while read dummy dummy dummy master_host master_user master_password master_port dummy ; do
  printf "CHANGE MASTER TO master_host = '%s', master_port = %d, master_user = '%s', master_password= '%s';\n" $master_host $master_port $master_user $master_password
done

ダメなクエリが延々流れてきてCPUが詰まっているのでとにかく来た順番にKILLしたい

  • grep次第で特定のクエリに絞ったり絞らなかったりができるあたりがよく使う所以か
$ mysql -sse "SHOW PROCESSLIST" | grep -v 'system user' | grep -v 'Binlog Dump' | awk -F"\t" -v timelimit=10 '$6 > timelimit && $5 != "Sleep"{print $1}' | while read id ; do
  mysql -e "KILL $id"
done

MySQL 8.0とそれ以降でも mysql_native_passwordのハッシュを知りたい

$ mysql -sse "SELECT CONCAT('*', UPPER(SHA1(UNHEX(SHA1('$raw_password')))));"

read用のVIPでちゃんと分散してるかどうか確かめる

  • forの外側で sort | uniq -cでちゃんと分散してるか数える
$ for n in {1..100}; do
  mysql -h $read_vip -sse "SELECT @@hostname"
done | sort | uniq -c

auto_incrementなカラムで梳きながらDELETEなりUPDATEなりする

$ for ((i=$min; i<=$max; i+=$limit)); do 
  mysql -ve "DELETE FROM t1 WHERE id BETWEEN $i AND $i+$limit AND $original_where_clause"
 sleep $sleep
done

圧縮しながらxtrabackupを取る

  • ファイルリダイレクトでなく ssh "cat - > .." とかにパイプすればリモートにも転送できる
$ xtrabackup -uroot --stream=xbstream --backup | pzstd -c > xtrabackup.xb.zst

圧縮済のxbstreamを展開する

  • ↑の逆パターン
    • カレントディレクトリに色々ぶちまけるのでワーキングディレクトリを作った方が良いと思う
$ pzstd -dc xtrabackup.xb.zst | xbstream -xv

トランザクションがなかなか途切れないテーブルにどうしてもALTER TABLEしたくて1秒までなら何とか我慢しながら成功するまでひたすらリトライする

  • 1秒までの他のクエリのブロッキングは許す(でないといつまでも終わらない)
  • オンラインALTER TABLEは「2回」メタデータロックを取るので、開始前と終了直前どちらでタイムアウトする可能性もある
    • 30分かかるALTER TABLEが終了処理のメタデータロックでタイムアウトしても泣かない
$ while true ; do
  mysql -sse "SET SESSION lock_wait_timeout= 1; ALTER TABLE t1 ADD KEY idx_something(some_column)" || break
  sleep 1
done

バックアップしたりリストアしたりKILLしたりALTER TABLE無限リトライなんてことをしょっちゅうやってるんですねわかります!()

明日は taka_yuki_04 さんです!

0 件のコメント :

コメントを投稿