一括りにデータベースのトランザクションと言っても、実はデータベースや設定によってトランザクションを複数走らせた時に、微妙に挙動が異なる場合があります。この違いは、データベースのACID特性のうちのIsolation(独立性)に関わる設定が違うため発生します。この設定はトランザクション分離レベルと言って、並列性やデータの整合性をどこまで求めるかによって適切に選ぶ必要があります。そこで今回は、MySQLでトランザクション分離レベルを変更する方法を紹介したいと思います。
検証環境
第10回 yum, rpmインストールにおけるMySQL 5.6とMySQL 5.7の違いで紹介されたyumリポジトリを使用したインストールを利用しています。また、MySQLのバージョンは5.7.18を使用しています。OSは、今回はCentOS 7.3上で確認を行っています。
現在のトランザクション分離レベルを確認する
変更を行う前に、現在のトランザクション分離レベルが一体どのような設定になるかを確認してみましょう。確認するには、以下のコマンドを実行します。txはTransactionの略称です。
最初は設定を変更していないため、globalとsessionで比較しても、デフォルトのREPEATABLE READが設定されていることがわかります。
トランザクション分離レベルを変更する
トランザクション分離レベルを変更する際には、以下の3つの方法があります。
- SET TRANSACTION構文を使って変更する
- mysqldから起動する際にオプションを指定する
- my.cnfに設定する
続いて、それぞれの設定方法に関して説明をしていきます。
SET TRANSACTION構文で変更する
まずは、SET TRANSACTION構文を使って変更します。この構文は以下のような構造をしています。また、この構文でGLOBALの変数を変更するためにはSUPER権限が必要なので注意してください。SET TRANSACTION構文は、トランザクション分離レベル以外にもREAD ONLYやREAD WRITEなども指定できますが、今回は説明を行いません。
指定できるトランザクション分離レベルとしてSERIALIZABLE
, REPEATABLE READ
, READ COMMITTED
, READ UNCOMMITTED
の4種類が選択できます。デフォルトではREPEATABLE READ
が設定されています。GLOBALやSESSIONオプションは、その設定がグローバルに設定するものなのか、そのセッション限りなのかを指定します。指定がされなかった場合は、指定を行ったセッションで次回に発生するトランザクションに、指定したトランザクション分離レベルが設定されます。
SESSIONで設定した場合はコネクションを再接続した際に、GLOBALで設定した場合は再起動した時に、設定が戻ってしまうことに注意が必要です。設定の永続化を行いたい場合は、後述するオプションを指定して起動するようにするか、もしくはmy.cnfで設定をするようにしましょう。うっかり忘れてしまうと思わぬタイミングで足をすくわれる事があります。
余談ではありますが、MySQL8.0ではSET PERSIST
というコマンドが追加されています。こちらを利用すると設定をコマンドラインから永続化することができます。このコマンドで設定した場合、mysqld-auto.cnf
にJSONファイルとして書き出され、読み込む際に一番最後に読み込みが行われます。
起動時にオプションを指定をする
CentOS7以降だとsystemctlコマンドを使って起動します。起動時に指定するOPTIONは、まとめてMYSQLD_OPTSというオプションに登録することで使えます。set-environment
オプションで設定を行います。一部キーワードがSET TRANSACTION構文と異なることに注意が必要です。オプションに使える値はSERIALIZABLE
, REPEATABLE-READ
, READ-COMMITTED
, READ-UNCOMMITED
の4つです。
再起動を行った後に起動後確認をすると、SERIALIZABLE
になっています。
またMYSQLD_OPSに設定したオプションを解除したい場合は、以下のようにsystemctl unset-environment
コマンドを実行して再起動すると元の設定に戻ります。
以上からデフォルトのREPEATABLE-READ
に戻っていることがわかります。もし、systemctlから設定が行われているかどうかを確認したい場合は、systemctl show-environment
コマンドで設定した環境変数が確認できます。
このように起動時にオプションとして設定することもできます。ただし後述するように、my.cnfでも設定をする場合は混在させると見落としがちなので、設定する場合はどの様に運用するかをきっちりと決めて明文化してから設定を行ったほうが良いでしょう。
my.cnfファイルで設定をする
my.cnfファイルの読み込み順やオプションファイルの書式に関しては、第31回 MySQLのオプションファイル my.cnfの豆知識[その1]と第33回 MySQLのオプションファイル my.cnfの豆知識[その2]に詳細な説明があるので、気になる方はそちらも合わせて参照してください。
my.cnfで指定する場合は、以下のように[mysqld]セクションで設定を行います。オプションに使える値は起動時にオプションで指定する時と同じSERIALIZABLE
, REPEATABLE-READ
, READ-COMMITTED
, READ-UNCOMMITED
の4つです。今回は/etc/my.cnf
内に以下の設定を行いました。
その後再起動を行い、確認した結果が以下のようになります。
設定がREAD-COMMITED
に変更されていることがわかります。
まとめ
今回はトランザクション分離レベルを変更する方法について紹介しました。トランザクション分離レベルの各設定の違いに関しては、次回以降で説明させていただきたいと思います。