連載
» 2007年04月09日 00時00分 公開

今から始める MySQL入門(5):MySQLの基礎を学ぼう [サンプル開発編] (1/2)

[鶴長鎮一,@IT]

 連載第4回「MySQLの基礎を学ぼう [準備編] 」では、MySQLの基本操作や今回取り上げるサンプル開発の下準備を行いました。今回は、「簡易オンラインストア」のサンプルコードを実際に見ながら、MySQLの使用方法や特長について理解を深めましょう!

関連リンク:

連載 快速MySQLでデータベースアプリ!

http://www.atmarkit.co.jp/flinux/index/indexfiles/mysqlindex.html

連載 今から始める MySQL入門

http://www.atmarkit.co.jp/flinux/index/indexfiles/mysql5index.html


MySQLサーバの利用(1)

サンプルのダウンロードと実行

 連載第3回「サンプルで理解! フォームデータの受け渡し」では、「簡易オンラインストア」を題材にPHPによるフォームデータの受け渡しについて解説しました。今回は、同じくサンプルコードを用いてMySQLサーバを利用したデータの受け渡し(参照/登録)方法について紹介します。

 まず、sample3のソースファイルをダウンロードして、Apacheのドキュメントルートに展開してみましょう。

サンプルダウンロード:

sample3のtarアーカイブ


# cd /var/www/html/ (ソースからインストールした場合は/usr/local/apache2/htdocs/)
# tar xvfz /..pathto../sample3.tgz

 展開後、ブラウザで「http://サーバ/sample3/menu.php」にアクセスすると実際に動作を確認できます。

解説

 連載第3回目のsample1sample2では、注文番号や受注データの保存にファイルを利用しました。

 ファイルでデータを保存する場合、操作は単純ですが排他処理の煩わしさやセキュリティ上の懸念点などが残ります(注)。また、Webサーバ上でしかデータを利用できないなど利用面でも問題が残ります。

注:ファイルの保存先が適切でなかったり、読み込み/書き込み権限が正しく設定されていないなどの理由でWebサーバから顧客情報が漏えいしたという事例は過去頻繁に見られました。


 このような問題を解決する手段の1つとして、MySQLのようなRDBMS(リレーショナルデータベース管理システム)が利用されています。

 それでは、sample3の中身を見ていきましょう。連載第3回のsample2との差異は次のとおりです。

  • メニュー画面(menu.php)
    • カウントデータをMySQLのcountテーブルのmax_noカラムから読み込む
    • カウントデータの読み込み後、カウント値を+1してmax_noカラムを更新
  • 確認画面(confirm.php)
    • sample2からの変更なし
  • 完了画面(purchase.php)
    • 受注データを2つのテーブルに登録。注文番号/現在日時/氏名/住所データはorder_mainテーブルに、注文番号/現在日時/アイテム名/個数は「order_item」テーブルに挿入

メニュー画面(menu.php)

 sample3の「メニュー画面(menu.php)」では、連載第3回目のsample1で行っていた「ファイル操作」から「MySQL操作」へ変更しています。

1   <?php
2   $mysqli = new mysqli("localhost", "php", "password", "sample_db");
3
4   if(mysqli_connect_errno()){
5     die("MySQLサーバ接続に失敗しました<br>
 理由:" . mysqli_connect_error());
6   }
7
8   $mysqli->autocommit(FALSE);
9
10  $result = $mysqli->query("SELECT max_no FROM count FOR UPDATE");
11
12  $row = $result->fetch_array(MYSQLI_NUM);
13
14  if( !$mysqli->query("UPDATE count SET max_no = max_no + 1;") ){
15    die("登録に失敗しました(1001) " . $mysqli->error);
16  }
17
18  $order_no = $row[0];
19  $mysqli->commit();
20  $result->close();
21  $mysqli->close();
(省略)
25  ?>
(省略)

2行目

連載第1回「MySQL+Apache+PHPをインストールしよう」では、MySQLサーバへの接続にmysqli_connect()を使用しました。ここでは、よりオブジェクト指向性を高めるためnew演算子を使用します。

4〜6行目

 引数には「("MySQLサーバのアドレス","ユーザーー名","パスワード","データベース")」を指定します。MySQL接続時にエラーが生じた場合、mysqli_connect_errno()にエラー内容が格納されます。ここでエラーの有無を確認し、エラーがあればそれを表示して処理を終了します。

8〜16行目

 countテーブルのmax_noカラムからカウントデータを読み込み、それに+1をしたものでmax_noを更新します。まず、トランザクション処理を利用できるよう8行目で自動コミットを無効にします。10行目では「SELECT max_no FROM count FOR UPDATE」を発行し、結果セットを$resultに格納します。$resultから値を取り出すためにfetch_array()で$rowに格納します(12行目)。カウントデータを更新する「UPDATE count SET max_no = max_no + 1」クエリーでは、念のためエラー確認を行います(14〜16行目)

 データベースから取得したカウントデータを注文番号に格納して(18行目)、トランザクションをコミットします(19行目)。その後、不要になった結果セットやMySQLコネクションを解放します(20、21行目)

 menu.phpでは「SELECT ... FOR UPDATE」を使用し、カウントデータに対して排他ロックを実施しています。排他ロックを用いていない場合に複数のユーザーが同時にmenu.phpへ接続するとカウントデータとなるcountテーブルのmax_noカラムの値が+1される前に別のユーザーがmax_noカラムを参照してしまう可能性があります。このような場合、同一の注文番号が複数のユーザーで使用されるという事態に陥ります。

 同じ注文番号が使用されないようにするためには「SELECT ... FOR UPDATE」で対象のデータが更新されるまでほかのトランザクションの「SELECT...FOR UPDATE」を待機させます。

確認画面(confirm.php)

 連載第3回目sample2からの変更点はありません。

       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。