CodingReptile

ゆるゆると技術に関するメモを貯めていく

SQLステートメントとMySQLで一貫性読み取りが機能しない場合

うっかり運用中のサービスでユーザから参照されるテーブルのパーティションを作成してしまい、MySQLの一貫性読み取りが機能しない場合に遭遇したのでまとめ。ついでに SQL ステートメントについてちゃんとドキュメントを読んだ。

一貫性読み取り

トランザクション分離レベルが REPEATABLE READ である場合、同一トランザクション内では最初の SELECT 文を発行した時点でスナップショットが作成され、以降はそのスナップショットを参照するため他のトランザクションによる変更の影響を受けない。

SQL ステートメント

DCL

データ制御言語 (Data Control Language)。権限を管理するための SQL ステートメント。以下のステートメントが含まれる。

  • GRANT(権限の付与)
  • REVOKE(権限の削除)

DML

データ操作言語 (Data Manipulation Language)。個々のテーブルを操作するための SQL ステートメント。以下のステートメントが含まれる。

  • INSERT
  • UPDATE
  • DELETE
  • SELECT .. FOR UPDATE

DDL

データ定義言語 (Data Definition Language)。データベース自体を操作するための SQL ステートメント。以下のステートメントが含まれる。

  • CREATE
  • ALTER TABLE
  • DROP TABLE
  • TRUNCATE(DELETE 文とは動作が異なる)

DDL ステートメントは自動的に現在のトランザクションをコミットし、それらをロールバックすることはできない。

一貫性読み取りが機能しない場合

特定の DDL ステートメントでは、一貫性読み取りが機能しない。

  • DROP TABLE

    MySQL が削除されたテーブルを使用できず、そのテーブルは InnoDB によって破棄されるため、一貫性読み取りが機能しない。

  • ALTER TABLE

    元のテーブルの一時コピーが作成され、元のテーブルは一時コピーが構築されるときに削除される。そのため、一貫性読み取りが機能しない。MySQL 5.6.6 時点では、ER_TABLE_DEF_CHANGED エラー「Table definition has changed, please retry transaction」が返される。

パーティション作成は ALTER TABLE なので、以下のような順序で操作が行われるとエラーとなってしまう。

  1. トランザクション開始
  2. tableA の参照クエリを発行 (ok)
  3. tableA のパーティション作成
  4. tableA の参照クエリを発行 (error)

参考URL