GA

2020/05/28

yt-rename-databaseでかつての RENAME DATABASE っぽいことをする

MySQLに RENAME DATABASE が存在していたのは 5.1.7から5.1.22の短い期間だけ(5.1のGAは5.1.30なのでその時にはもう消えていた)

にも拘わらず、かつての日本語版ドキュメントのカバー範囲が「5.1.15-betaまで」なため、俺と似たような時期に日本語ドキュメントを使って勉強していた人はよく知っているイメージ。

ちなみに無くなった理由は「色々考慮してないものが多すぎて色々壊れまくったから」だと思う(個人の見解です)


とはいえごく稀に、「現在のデータベースを他の名前にリネームして切り戻し用にとっておきたい(データだけでも)」ということはあるので、 RENAME DATABASE を模した動きをするスクリプトを作った。

その名も yt-rename-database
Yoku-san no ToolKIT の仲間なので、CentOS 7.xなら releaseごとにrpm を作ってある。
(ただし 0.2.1-0 にはバグがあって yt-rename-database --help ができない…(゚∀。)

$ /usr/local/bin/yt-rename-database --help
..
* --ask-pass, --ask-password, --askpass
  Ask --password by prompt

* --debug
  Set debug output

* --dest=value, --destination=value, --dst=value, --to=value
  Database-name moving to

* --execute
  Execute statements. If --execute is not specified, only print statements.

* --force, -f
  Force RENAME if --to has TRIGGERS, EVENTS, ROUTINES, VIEWS, and Foreign Keys.

* --from=value, --source=value, --src=value
  Database-name moving from

* --help, --usage
  Show this message

* --host=value, -h=value { Default: localhost }
  MySQL host

* --ignore-event, --ignore-events
  Force RENAME if --to has EVENTS.

* --ignore-fk
  Force RENAME if --to has ROUTINES.

* --ignore-routine, --ignore-routines
  Force RENAME if --to has ROUTINES.

* --ignore-trigger, --ignore-triggers
  Force RENAME if --to has TRIGGERS.

* --ignore-view, --ignore-views
  Force RENAME if --to has VIEWS.

* --password=value, -p=value
  Password for the user specified by --user

* --port=value, -P=value
  MySQL port number

* --quiet, --silent, -q, -s
  No output any messages

* --socket=value, -S=value
  Path to mysql.sock
  (this parameter is used when --host=localhost)

* --timeout=value { Default: 1 }
  Seconds before timeout
  (Set into read_timeout, write_timeout, connect_timeout)

* --user=value, -u=value
  MySQL account using for connection and checking
  (need REPLICATION CLIENT, PROCESSLIST and global SELECT priv)

* --verbose, -v
  Verbose output mode

* --version, -V
  Show ytkit version

..

接続関連のオプションは mysql コマンドラインクライアントのものとほぼ一緒。
地味に ytkit で一番気に入ってるのはオプションパーサーで、MySQL公式のクライアント群を模して --socket=/tmp/mysql.sock, --socket /tmp/mysql.sock, -S /tmp/mysql.sock, -S/tmp/mysql.sock が全部ちゃんとパースできる(おまけに公式ではできない -S=/tmp/mysql.sock もできる)

-p の引数が空っぽの時のハンドルは模すのが面倒だったので percona-toolkit や innotopみたいに --askpass オプションがついている(これ、ptとinnotopで確か —ask-passと—askpassと揺れててたまに間違えるので両方とも受け取れるようにしてる)

--from--to が必須オプションになっていて、そいつらを指定しているとこんな風にペロッと「 RENAME TABLE で中身を全部新しいスキーマに移す」ようなSQLスクリプトを吐く。

$ /usr/local/bin/yt-rename-database -uroot -S /usr/mysql/8.0.20/data/mysql.sock --askpass --to=d11 --from=d1
Password:
-- Emulating RENAME DATABASE d1 TO d11
-- I'm dry-run mode. Specify --execute if you wish to execute statements by script.
CREATE DATABASE `d11`;
-- I'm dry-run mode. Specify --execute if you wish to execute statements by script.
RENAME TABLE `d1`.`t1` TO `d11`.`t1`;
-- I'm dry-run mode. Specify --execute if you wish to execute statements by script.
DROP DATABASE `d1`;

もとの RENAME DATABASE 時代にひどい目に遭ったらしいForeignKeyやTrigger, Viewなどがあるとそのままではエラーになる。

$ /usr/local/bin/yt-rename-database -uroot -S /usr/mysql/8.0.20/data/mysql.sock --askpass --from=admintool --to=_admintool
Password:
-- Emulating RENAME DATABASE admintool TO _admintool
admintool has Foreign Keys, not supporting.(For *forcing-execution*, use --ignore-fk or --force) at /home/yoku0825/git/ytkit/bin/../lib/Ytkit/RenameDatabase.pm line 99.

警告を無視する(その辺の不整合はセルフでカバーする)場合のオプションはエラー出力に含まれるようになっている(さっきコミットしたばっか)。

$ /usr/local/bin/yt-rename-database -uroot -S /usr/mysql/8.0.20/data/mysql.sock --askpass --from=admintool --to=_admintool --ignore-fk  --execute
-- Emulating RENAME DATABASE admintool TO _admintool
-- admintool has Foreign Keys, not supporting.(For *forcing-execution*, use --ignore-fk or --force) at /home/yoku0825/git/ytkit/bin/../lib/Ytkit/RenameDatabase.pm line 93.

--execute をつけると実際にスクリプトを実行してリネームする。
あんまり使うこと考えてなくて、 --execute なしでSQLスクリプトとして出力させてぺたこんと貼ればいいんじゃないかなと思っている。

基本的に SHOW TABLESRENAME TABLE を使っているだけなので、ワンライナーでも余裕でいけると思う。

$ mysql -uroot -sse "SHOW TABLES FROM <from_db>" | while read table ; do
>   mysql -uroot -ve "RENAME TABLE <from_db>.$table TO <to_db>.$table"
> done

ふと思ったので作ってみたのでした。

0 件のコメント :

コメントを投稿