WEBデザイン・開発講義WEB Design&Development Lecture

「MySQL」のトランザクション処理とSQLコマンド

「MySQL」のトランザクション処理及びSQL文法とコマンド操作

「MySQL」のトランザクション処理とデータベース作成、SQLコマンド操作の実践

「MySQL」のトランザクション処理※画像クリックで拡大表示(リンク)

  • トランザクション処理とは
    複数の作業を連結した処理単位を「トランザクション」といい、トランザクションとして管理された処理は「すべて成功」か「すべて失敗」のどちらかの保証が必要です。
    DBトランザクション処理とロック制御
    • トランザクション処理コミット
      あるレコード更新する場合に、まず検索(SELECT文)して、その後変更した内容を更新する(UPDATE文)連続した処理が必要になります。この連続した処理がトランザクション処理であり、処理途中でエラーが発生した場合には、「ロールバック」というトランザクション開始位置(セーブポイント)に戻って処理を継続することが求められます。
      トランザクション処理がOKのときには、コミット(COMMIT文)して、処理を進めます。通常の処理では、更新(UPDATE文)ごとに自動的にコミットするモード(AUTO COMMIT)になっておりますので、トランザクション処理では、「AUTO COMMIT」をオフにして処理をすることが一般的です。
    • ロック制御の必要性
      複数の処理が同時に実行されているデータベースで、ある処理「A」が入庫処理の追加更新する場合は、最初に該当する商品を検索(SELECT文)し、格納されている在庫数「100個」に入庫のデータの入庫数「10個」を加算して在庫数として更新(UPDATE文)する処理です。
      別の処理「B」で出庫するため、たまたま同じ商品を検索(在庫数「100個」)して、「A」の入庫処理の更新前に出庫処理「20個」をしたときの在庫数「80個」として更新すると、その直後に「A」の在庫数「110個」で更新した場合に、処理「B」の出庫数が反映されず在庫数の矛盾が発生してしまいます。
      この矛盾を防止するため、先の処理(この例では「A」)の更新が終了するまで、他の処理(この例では「B」)が待たされる「ロック」制御(排他制御)が必要になります。ロック制御が「レコード単位」(一般的に自動でロック)か「テーブル単位」(一般的に手動でロック)かにより、処理スピードが大きく変わってきます。
    • 分離レベルのモード
      分離レベル「ISOLATION LEVEL」は、「SQL92」で規定されている次の4つがあり、あるトランザクション処理と別のトランザクション処理の分け隔たり(分離)の設定が可能です。
      ・「READ UNCOMMITTED」:他の処理によって行われている、書きかけのデータまで読み取る(コミットされる前の変更をみる)ことが可能
      ・「READ COMMITTED」:コミットされた時点での変更をみることが可能
      ・「REPEATABLE READ」:コミットされるまでトランザクション内で読み取り(同じSELECT文)を何回実行しても、同じ値となることを保証(MySQLのデフォルトモード)
      ・「SERIALIZABLE」:コミットされるまでテーブルロックされ、トランザクションを1つ1つ順に実行(最も安全にデータを操作できるが、相対的にスピードが遅くなる)
      【 分離レベルとデータの読み取り方 】
      分離レベルダーティリードノンリピータブルリードファントムリード
      READ UNCOMMITTED
      READ COMMITTED
      REPEATABLE READ*
      SERIALIZABLE

      (注)*:MySQLの「InnoDB」エンジンを利用した場合はファントム・リードが起きません。

  • MySQLのデータベースエンジン比較と選択
    エンジンMyISAMInnoDBNDB
    最大格納容量256TB64TB384EB
    トランザクション
    ロック精度テーブル
    MVCC
    クラスタDB
    インデックス特徴前文検索クラスタ化ハッシュ
    特徴インデックスキーをコントロールACIDトランザクション処理クラスタ化データベースサポート
    トランザクション処理には、デフォルトの「InnoDB」データベース・エンジンが最適です。
  • データベース・エンジンを確認するには、
    show table status」のコマンド入力で表示されます。
    データベース・エンジンを確認するコマンド

トランザクション処理データベース作成とSQLの修飾句コマンド操作

  • トランザクション処理の「ec_trans」データベース作成
    トランザクション処理の理解する上で、事例として下記に「商品トランザクション処理のER図」を示します。
    商品トランザクション処理のER図
  • 「SQL」コマンド「SELECT」文の修飾句の操作
    「注文明細トランザクション」のテーブルを利用して、「SELECT」文の修飾句を理解し、SQLコマンドの操作を実践します。
    【 注文明細トランザクション:「SELECT」文の修飾句 】
    修飾句説明とコマンド例
    DISTINCT重複する行を取り除いて表示する
    sql> select distinct order_number, order_date, customer_id from order_detail;
    WHERE条件を指定する
    sql> select order_number,order_date from order_detail where order_date='2014-05-06';
    GROUP BYデータをグループ化する
    sql> select order_number, count(*), customer_id from order_detail group by order_number;
    HAVINGグループ化されたものに条件を設定する
    sql> select order_number, count(*) as item_num, customer_id from order_detail group by order_number having item_num>1;
    ORDER BY結果の並び順を指定する
    sql> select order_number, sum(quantity * order_price) as amount,order_date from order_detail group by order_number order by amount desc;
    LIMIT指定した部分だけを結果として取得する
    sql> select order_number, sum(quantity * order_price) as amount,order_date from order_detail group by order_number order by amount desc limit 5;
    注文明細の「SELECT」修飾句のコマンド操作例:「orderDetail_select_operation.sql」のダウンロード
    理解を深めるため、操作事例を参考にして、コマンド操作を実践してください。
  • 「SELECT」文の修飾句操作の実践(ビデオ表示)
    「order_detail」テーブルの修飾句の操作:1
    (9分40秒)
    「order_detail」テーブルの修飾句の操作:2
    (7分36秒)

トランザクション処理のコマンド操作

  • MySQLのトランザクション処理のSQLコマンド
    SQLコマンド内容
    SET TRANSACTION ISOLATION LEBEL {xxxx}トランザクション分離レベルの設定
    {xxxx}の4つのモード指定(上記参照)が可能
    START TRANSACTIONトランザクション処理の開始(ロックの初期化)
    BEGIN
    COMMITトランザクション処理の確定
    SET AUTOCOMMIT = {0 | 1}AUTO COMMITモードのON「1」とOFF「0」の設定
    SAVEPOINT 名前セーブポイントの「名前」を設定
    ROLLBACK TO SAVEPOINT 名前「名前」のセーブポイントへ
    ロールバックをする
    SELECT ...
    FOR UPDATE
    行ロックをする(手動ロック)
    LOCK TABLES と
    UNLOCK TABLES
    テーブル (ビュー以外) をロック と
    ロック全てを解放
    テーブルの更新処理で、トランザクションをエミュレートやスピードアップの際に利用(手動ロック)
  • トランザクション開始と終了コマンド操作
    MySQLコマンドプロンプトの初期操作で、「er_trans」のデータベースを選択して、どのようなテーブルがあるかを確認。
    MySQLコマンドプロンプトの初期操作
    • トランザクション開始とロールバック操作
      トランザクション開始「START TRANSACTION」文を実行し、「products」テーブルの「product_id」カラムが 'p140500004'であるレコードに対して、「order_quant」カラムの値を「99」に更新するUPDATE文を実行する。その後「ROLLBACK」文でUPDATE文の実行内容が無効であることを確認できます。
      現在の内容確認とトランザクション開始「start transaction」とロールバック操作で更新処理の無効確認
    • トランザクション開始とコミット操作
      トランザクション開始「BEGIN」文を実行し、「products」テーブルの「product_id」カラムが 'p140500004'であるレコードに対して、「order_quant」カラムの値を「99」に更新するUPDATE文を実行する。その後「COMMIT」文でUPDATE文の実行内容が有効となったことを確認できます。
      トランザクション開始「begin」とコミット「commit」操作で更新処理の有効確認
    • トランザクション開始とセーブポイント操作
      トランザクション開始「BEGIN」文を実行し、「ship_detail」テーブルに1件のデータ:伝票番号「t14050008」を挿入します。その後、セーブポイント「SAVEPOINT tr01」を設定します。1件のデータ:伝票番号「t14050009」を挿入し、伝票番号「t14050004」の数量を「9」に変更更新して、「ship_detail」テーブル内容を確認し、セーブポイントまで戻る「ROLLBACK tr01」文を実行。
      トランザクション開始「begin」とセーブポイント指定して、挿入・更新・検索と指定位置へロールバック操作
      指定された名前のセーブポイントの位置の処理までにロールバックした内容「セーブポイント以降の挿入と更新処理が無効であること」の確認ができます。
      セーブポイントの位置の処理までにロールバックした内容「挿入・更新が無効」の確認
      続けて「ロールバック」を実行するとトランザクション開始「BEGIN」文の位置までの処理の伝票番号「t14050008」の挿入が無効となっていることが確認できます。
      「ロールバック」を実行するとトランザクション開始「begin」の位置までの処理が無効の確認
  • トランザクション処理のコマンド操作(ビデオ表示)
    「products」テーブルのトランザクション開始と終了コマンド操作(4分19秒)
    「ship_detail」テーブルのセーブポイントとロールバックのコマンド操作(6分47秒)
  • トランザクション処理分離レベルのコマンド操作
    トランザクション開始前に「SET TRANSACTION ISOLATION LEVEL xxx」の分離レベルを設定します。
    今回の操作は、2人のユーザが同じテーブルを同時操作する前提のコマンド操作です。
    ユーザ [A] の操作ユーザ [B] の操作
    REPEATABLE READの例
    [A]
    SET AUTOCOMMIT=0;
    BEGIN;
    SELECT * FROM tbl WHERE id=2;
    「id=2」の「clmn」が'xx'を表示
    [B]
    SET AUTOCOMMIT=0;
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    BEGIN;
    SELECT * FROM tbl WHERE id=2;
    「id=2」の「clmn」が'xx'を表示
    [A]
    UPDATE tbl SET clmn='aaa' WHERE id=2;
    SELECT * FROM tbl WHERE id=2;
    UPDATE文実行で、「id=2」の「clmn」が'aaa'を表示
    [B]
    SELECT * FROM tbl WHERE id=2;
    「id=2」の「clmn」が'xx'を表示(値が変わらない
    [A]
    INSERT INTO tbl VALUES(5,'zzz',..);
    SELECT * FROM tbl;
    INSERT文実行で、追加した「id=5」の「clmn」'zzz'も表示
    [B]
    SELECT * FROM tbl WHERE id=2;
    「id=2」の「clmn」が'xx'を表示
    「id=5」の追加分は表示されない(値が変わらない)
    [A]
    COMMIT;
    SELECT * FROM tbl WHERE id=2;
    UPDATE,INSERT文の実行結果の反映した内容を表示、「id=2」の「clmn」が'aaa'、「id=5」の「clmn」が'zzz'
    [B]
    SELECT * FROM tbl WHERE id=2;
    「id=2」の「clmn」が'xx'を表示、「id=5」の追加分は表示されない(同一トランザクション内で値が変わらない
    →「InnoDB」のため、ファントムリードが起きない
    SERIALIZABLEの例
    [A]
    SET AUTOCOMMIT=0;
    BEGIN;
    SELECT * FROM tbl;
    「id=2」の「clmn」が'xx'を表示
    [B]
    SET AUTOCOMMIT=0;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    BEGIN;
    SELECT * FROM tbl;
    「id=2」の「clmn」が'xx'を表示
    [A]
    UPDATE tbl SET clmn='aaa' WHERE id=2;
    ロック状態のため、[B]の実行結果待ち
    [B]
    ROLLBACK;
    Transaction終了し、共有ロックを解放
    [A]
    ロックが外れたのでUPDATEが実行される
    SELECT * FROM tbl;
    UPDATE文の実行で、「id=2」の「clmn」が'aaa'を表示
  • トランザクション分離レベルのコマンド操作(ビデオ表示)
    トランザクション分離レベルの「REAPEATBLE READ」コマンド操作(9分43秒)
    トランザクション分離レベルの「SERIALIZABLE」コマンド操作(4分54秒)

MySQLの補足説明

MySQLリファレンス

参考資料の表示

推奨参考図書

pagetopへ