【PHP】SQLServerのトランザクションの確認、操作方法

PHP

【PHP】SQLServerのトランザクションの確認、操作方法

データベースを操作する際、実際のアプリでは必ずトランザクションの使用します。
SQLServerのトランザクションの操作方法を紹介します。

そもそもなぜトランザクションが必要なのか

トランザクションが必要なケースは、例えば、店舗1から店舗2にりんごを10個送ったとします。データベース上では店舗1から在庫を減らして店舗2の在庫を増やすという処理が必要ですが、店舗1のSQLだけ成功して店舗2のSQLが失敗した場合、在庫数がおかしくなります。
そこでトランザクションが必要となります。
トランザクションとは何か?については、【MySQL】トランザクションとACID特性を参考にしてみてください。

トランザクションの書き方

店舗1から店舗2にりんごを10個送ったとします。
その場合は、以下のように記述します。

try {

  $user = 'hoge';
  $pwd = 'hoge';
  $host = 'localhost';
  $dbName = 'hoge_db';
  $dsn = "mysql:host={$host};port=8889;dbname={$dbName};";
  $conn = new PDO($dsn, $user, $pwd);
  // 連想配列のみ出力
  $conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  // エラーを有効にする
  $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  // prepare()を使うための設定
  $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

  $product_id = 2;
  $from_shop_id = 1;
  $to_shop_id = 2;
  $amount = 20;

  // pst = prepared statement
  $pst = $conn->prepare('
      update txn_stocks
      set amount = amount + :amount
      where shop_id = :shop_id
      and product_id = :product_id
  ');

  // トランザクションを開始する
  $conn->beginTransaction();

  // 在庫を足す
  $pst->execute([
      ':amount' => $amount,
      ':shop_id' => $to_shop_id,
      ':product_id' => $product_id
  ]);
  // 在庫を減らす
  $pst->execute([
      ':amount' => -1 * $amount,
      ':shop_id' => $from_shop_id,
      ':product_id' => $product_id
  ]);

  // 成功したときにcommitでデータを反映
  $conn->commit();


} catch (PDOException $e) {

  echo 'エラーが発生しました。
'; echo $e->getMessage(); // コネクションが失敗したとき $conn->rollBack(); }

トランザクションを開始するには、以下のように記述します。

// トランザクションを開始する
$conn->beginTransaction();

これ以降は同じセッションとして扱われます。

例外処理try-catchを記述して、

// 成功したときにcommitでデータを反映
$conn->commit();

上の記述で成功したときのデータをデータベースに反映されることができます。
在庫数などはunsignedなどマイナスにならないように通常は設定しているため、在庫数を減らしてマイナスになる値になるとエラーになります。
そのとき、catchブロックに処理が飛びます。
データベースに反映させたくないため、rollBack()で巻き戻します。

PHP

Posted by devsakaso