7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

mysqlコマンドラインからSQLファイルを1トランザクションで実行する方法

Last updated at Posted at 2017-03-21

複数行からなるSQLファイルがあったとして、それを一括で実行したいとします。

sqls_no_transaction.sql
insert into foo (...) values (...)
update foo set ... where ...
insert into bar (...) values (...)
update bar set ... where ...

これらを mysql コマンドラインから一気に流すわけですが、一気で流すなら明示的にトランザクション内で実行したほうが早いのは誰でも予想できると思います。

実際、ある40000行のupdate文を明示的にトランザクション内で実行した場合と、実行しない場合の実行速度をtimeコマンドで計測してみました。

  • 明示的トランザクション内
$ time mysql < sqls_with_transaction.sql
real	0m21.692s
user	0m0.756s
sys	0m1.524s
  • 明示的トランザクションなし
$ time mysql < sqls_no_transaction.sql
real	1m53.670s
user	0m0.916s
sys	0m1.432s

6倍近くの差が出てしまいました。差は歴然ですね。

さて、ここからが本題。
明示的トランザクション下で実行するのであれば、begin;commit; で SQL文を囲めばよいわけですが、元のSQLファイルを修正できない(面倒な)場合はどうしたら良いでしょうか。

PostgreSQLのコマンドラインであるpsqlであれば、-1 (--single-transaction)というオプションがあり、自動的に明示的トランザクション下でSQL文を実行してくれます。しかし、mysqlにはありません。

そこでsedを使います。sedにはiコマンド(指定行の前に行を追加)、aコマンド(指定行の後に行を追加)があるので、

cat sqls_no_transaction.sql | sed -e '1ibegin;' -e '$acommit;'

とすれば、先頭行の前にbegin;、最終行の後ろにcommit;が追加できます。

begin;
insert into foo (...) values (...)
update foo set ... where ...
insert into bar (...) values (...)
update bar set ... where ...
commit;

あとはこれをパイプでmysqlに流すだけです。

cat sqls_no_transaction.sql | sed -e '1ibegin;' -e '$acommit;' | mysql

sedというとsコマンド(正規表現による置換)がポピュラーですが、ファイルの内容をちょっと一時的に加工したい場合に便利なツールなのだなと改めて実感しました。
使いこなすのは相当難しいとは思いますが。(笑)

追記: mac OS X上のsedはbsd系の実装なので、sedのコマンド指定方法が異なります。以下を使ってください。

cat sqls_no_transaction.sql | sed -e '1i\'$'\n''begin;' -e '$a\'$'\n''commit;' | mysql
7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?