QA@IT

php dbにデータを挿入する際のLOCK TABLES について

3164 PV

お世話になります。
当方の環境は、PHP5.2.13、mysql5.0.41です。

現在、csvをアップロードするphpを作成しています。

csvには作業データ+作業明細データが1レコードとして入っています。
tbl_work(作業テーブル)に作業データを格納し、
tbl_workdetail(作業明細テーブル)にデータを格納します。

foreach($work as $no=>$value){
 //★★

 if($tmp_empno!=$empno){
  //クエリを実行
  $rs=exeQuery("select max(work_no) as maxwork_no from tbl_work");
 }

 //tbl_work用のinsert文を作成

 //tbl_workdetail用のinsert文を作成


 //tbl_workの更新処理

 //tbl_workdetailの更新処理

 //トランザクションをコミット、テーブルをアンロック

}

csvをアップロード中に他のユーザからtbl_work、tbl_workdetailのデータを変更させなくしたいのですが、
//★★の部分で
LOCK TABLES tbl_work WRITE, tbl_workdetail WRITE
を行うのが正しいのでしょうか?
foreachの中で、LOCK TABLES を行うと負荷がかかりますか?
御教示くださいますと幸いです。

回答

下記、御教示ありがとうございました。
CSVは最大で500件位のデータを想定しています。

foreachでcsvをループし、その中でコミットしているのは、
tbl_work(作業テーブル)が親で、tbl_workdetail(作業明細テーブル)が子となっています。

  //クエリを実行
  $rs=exeQuery("select max(work_no) as maxwork_no from tbl_work");

でtbl_work[work_no]の最大値を取得し、+1したものを、

 //tbl_workdetail用のinsert文を作成

の時に入れて、子と認識できる様にしています。
foreachの中でコミットしないと、最大値が取れないと思ったため、その様にしたのですが、、、

flied_onion様の御回答を参考に、検証してみたいと思います。
ありがとうございました。

編集 履歴 (2)

work_noの整合性を維持したいのでロックしたいということでしょうか。

どの部分の負荷を気にしているかにもよりますが、個人的に気にするほどでもないとは思ってます。
ただ実際のところは測ってみるしかないかと思います。仮にInsert文の作成にすごく時間がかかるなら、その間ブロックされますのでそれはそれで問題ですし、csvの件数にも左右されるでしょう。

なお、LOCK TABLES自体は使うことで高速化が望まれます。


以下、質問の内容とは少し外れますので回答されなくてもかまいません。
トランザクションがループの中にあっても問題ないのですか?
そのforeachでcsvの行を回している様に思われるんですが途中でエラーが発生した場合にcsvの一部が取り込まれる状態になるように思われますが(コミットしてるので)、問題ないです?
csvの件数が多くなければトランザクションごと外のほうがいいような。

ちなみにLock Tablesはトランザクションアンセーフらしいので、呼ぶとコミットされます。

編集 履歴 (0)
  • 御教示ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。