データをロック中にエラーチェックを行うべきか?

このQ&Aのポイント
  • データをロック中にエラーチェックを行うべきか?エラーチェックとロックの順序に関しての検討
  • データをロック中にエラーチェックを行うべきか?エラーチェックとロックのタイミングについて考える
  • データをロック中にエラーチェックを行うべきか?ロックとエラーチェックの関係を考える
回答を見る
  • ベストアンサー

データをロック中にエラーチェックを行うべきか?

PHP5.2.4、MySQLバージョン4.1.16を使用しています。 次のように、データをロックする前にエラーチェックを行い、 エラーじゃなかったら更新処理を行うという書き方なのですが、 これだとエラーチェックとSTART TRANSACTION;(ロック開始)の 間で$pointが10以上になるか心配なのですが、そのようなことは ありえるのでしょうか? 心配するぐらいならSTART TRANSACTION;してから エラーチェックを書けばいいのでしょうが、 それだとROLLBACKの処理も絡んできそうで厄介なので できればこのように書きたいのですが・・・ ※ $pointとはそのユーザが所有しているデータの一部です(つまり任意のタイミングで書き換えが可能) if ($point >= 10)//←ここでチェックを行い、エラーなら抜ける {  error('pointが10以上です');  exit(); } ↑ // この間で$pointが10以上になる可能性が心配 ↓ START TRANSACTION;//←ロック開始 //ここに更新処理 COMMIT;

  • PHP
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

$pointを変更できないようにしてから処理を行わない限りは、「エラーチェックとロック開始までの間で10以上になる」ことは当然あり得るでしょう。 厳密には、ユーザのデータを$pointにセットしてから、実際に$pointをプログラム内で使う前に、別のプログラムでユーザのデータが変更される、という意味ですよね? まず$pointでユーザデータを取得しているテーブルをロックしてユーザのデータを変更不可にしてから10以上かチェックし、10以上だったら処理をせずにロックを解放してエラーを出力して終了、と書けるなら、それでいけると思いますが如何でしょうか。 ちなみに、ロールバックが厄介だろうが何だろうが、可能性があって、それがマズいなら、実装するしか無いと思います。 というか、厄介とかのレベルじゃなくて、ロールバック処理は当然の事だと思います。 別に、少々値がどうであってもかまわない、というのでなければ、プログラマが「面倒」などという理由でコーディングを省略するような事はやめた方が良いですよ。

takagoo100
質問者

お礼

ご返答ありがとうございます。 たしかにプログラムする上で当然のことですよね・・・ どうも自分の中で楽して記述したいという意識が強くて、 こういう思考になってしまいます・・・ 参考になりました。ありがとうございます。

関連するQ&A

  • トランザクションについて

    トランザクションについての質問なのですが、下にある1のSQLを実行すると 'a'だけ登録されるのは、分かるのですが、 2のSQLを実行すると、'c'と'd'の両方が登録されてしまいます。 私的には、両方登録されないのかなぁと思っていたのですが・・・ COMMITが来た時点で、START TRANSACTIONの開始位置は、 あまり関係ないということなのでしょうか? よろしくお願いします。 1. START TRANSACTION; insert into test values('a'); START TRANSACTION; insert into mtuser values('b'); ROLLBACK; COMMIT; 2. START TRANSACTION; insert into test values('c'); START TRANSACTION; insert into mtuser values('d'); COMMIT; ROLLBACK; 環境:Mysql4.1.19

    • ベストアンサー
    • MySQL
  • MySql5でのネクストロックについて

    mysql5(repeatable read)のロック機構について勉強しています。 [sample1(主キー:id)] +----+---+ | id | point | +--+-----+ | 10 | 10 | | 15 | 15 | | 20 | 20 | | 25 | 25 | | 30 | 30 | +--+-----+ 上記のようなテーブルに対して、以下の2つのスレッド(A,B)にて SQLを発行した際、☆1部分は即時に実行されます。 (A) start transaction; (A) select * from sample1 where id >= 15 and id <= 25 for update;  (B) start transaction;  (B) insert into sample1 values(14, 14); #☆1  (B) rollback; (A) rollback; しかし、以下の2つのスレッド(A,B)にて SQLを発行した際、☆2部分は即時に実行されません。(スレッドAのロック解除待ちになります) (A) start transaction; (A) select * from sample1 where id >= 15 and id <= 25 for update;  (B) start transaction;  (B) insert into sample1 values(26, 26); #☆2 (A) rollback;  (B) rollback; ネクストロックという機構があることは存じているのですが、その具体的な仕組みがよくわかりません。 どうして、☆1が即時に実行され、☆2はロックがかかってしまうのでしょう?

    • ベストアンサー
    • MySQL
  • トランザクションが原因?DBにデータ追加出来ません

    言語:PHP Framework:symfony DB:MySQL DBにデータを追加したいのですが、 [Rollback failed. There is no active transaction.] といったエラーが表示され、追加することが出来ません。 【ソース】 ------------------------------------------------------ try { $connection->beginTransaction(); ★DB追加処理; $connection->commit(); } catch (Exception $e) {   // ここで[Rollback failed. There is no active transaction.]というエラーが表示されます echo $e->getMessage(); $connection->rollBack(); } ------------------------------------------------------ DB追加処理の部分でエラーとなり、catchに飛ばされていたので、初めは追加の方法が間違っているのかと思ったのですが、下記の3つをソースから外すと正常に追加されました。 $connection->beginTransaction(); $connection->commit(); $connection->rollBack(); ※正確に言うと「$connection->beginTransaction();」を外すだけで追加出来ました。 また、これは私の勘違いかもしれませんが、初めてこの処理を行った時は正常にDBに追加されました。 実際にDBにデータが入ったのを確認しています。 ですが、2回目以降?からは、上記のように[Rollback failed. There is no active transaction.]というエラーが表示され、追加出来なくなりました。 ちなみにDB接続にはPDOというものを使用しているようです。 追加処理の部分に関してはSymfonyの方法で、下記のように実装しています。 ------------------------------------- $user = new T_USER(); $user->setName($name); $user->setAge($age); $user->save(); ------------------------------------- 何かヒントになるようなことでも構いませんので、分かる方がいらっしゃいましたらよろしくお願いします。 質問の内容に不備な点がございましたら、申し訳ありません。 以上です。

    • ベストアンサー
    • PHP
  • select実行時のロックとcommitについて

    お世話になっております。 WEB上で検索すると、select実行時にもロックを取得しcommitもしくはrollbackを実施していることがわかりました。 そのことについて数点疑問を持ち調査したのですが、わかりませんでした。 どなたかわかる方ご教示ください。 (1) select発行時にロックを取得しcommitもしくはrollbackするという認識は正しいでしょうか。 (2) 通常SQLに不備が無ければselectは正常に終了すると思いますが、 rollbackするのはどのような状況でしょうか。 selectのSQLに不備があった場合でしょうか。 (3) コンソールからselectを発行するとcommitせずとも結果が出力されます。 このcommitされるタイミングはいつになるのでしょうか。 (4) WITH URオプションを使用するとロックを取得しないと思いますが、 ロックを取得しないということはcommit/rollbackも実施されないという認識は正しいでしょうか。 (5) commitコマンドを発行するとアクティブログに追記されるという認識なのですが、 WITH URオプションなしでselect文を発行してもアクティブログに追記されるものでしょうか。 それともテーブルの更新など実施しないので、アクティブログは更新されないのでしょうか。 (6) WITH URオプションをつけてSELECTを実施した場合はアクティブログは更新されないでしょうか。 (7) EXPORTコマンドを実行した場合も(5)(6)と同様という認識で正しいでしょうか。 以上になります。 よろしくお願いいたします。

  • ロックについて

    データベース初心者ですが、よろしくお願いします。 トランザクション処理のロック制御について質問です。 例えば、ユーザAが表に対しupdateを行い、commitを行わなかったとします。このときに、他のユーザBがその表に対しupdateを行った場合、エラーになるのでしょうか? 私は、トランザクション処理というのは、表操作を行ってからcommitするまでの間をひとくくりとして、その間はロックがかかると認識しています。 どなたかご教授願います。

  • postgresqlのトランザクションについて

    開発環境(centOS、apatch、php、postgresql) postgrsqlで「current transaction is aborted, commands ignored until end of transaction block」 のエラーが出てしまいました。 ・複数テーブルに対してinsertを行っています。 ・複数tableのinsert中のどこかでエラーになった場合、全tableをrollbackしたいです。 ・複数テーブルのうち、ひとつのtableでは5回insertを行っています。   for文でまわしているのですが、ここで2回目のinsertの時に   上記のエラーになってしまいます。 で、トランザクション(begin、rollback、commit)を全てはずしたところ、全てのtableで正常にinsertできました。 上記のエラーを調べてみても rollbackしていない・・・みたいなことしか調べられませんでした。 エラーにはなっていないのでrollbackはしないし、ここでcommitしてしまうと、次のinsertなどでエラーになった時、rollbackできなくなってしまうし。。。 上記のエラーをなくすために どのような対策をすればいいのかアドバイスをお願いいたします!

  • VB5+SQL2000での ** TRANSACTIONについて(ADO)

    環境:VB5(SP3)+SQL2000(SP1) VBで、BEGIN TRANSACTIONを定義し、その後更新用DBを更新する前に、ストアドプロシージャを利用せずDBを検索した場合、問題無く更新用DBへの更新に対して(ROLLBACK/COMMIT) TRANSACTION が効くのですが、ストアドプロシージャで検索した場合、(ROLLBACK) TRANSACTION が効きません。 分かりづらいですがサンプルを記します。 Function Test() Dim MyRs As New ADODB.Recordset Dim MyRs2 As New ADODB.Recordset : MyDB.Execute "BEGIN TRANSACTION TEST999",,adCmdText+adExecuteNoRecords : '(A)不具合未発生パターン 'レコードセットを開く 'このように、レコードセットを作成した場合問題なし。 MyRs.Open "SELECT * FROM TESTDB..テスト",MyDB,adOpenStatic '(B)不具合発生パターン 'ただし、上のSELECT文をストアドプロシージャで開いた場合、ROLLBACKが効かない 'レコードセットを開く(正常に(ROLLBACK)TRANSACTIONが動作せず、UpDate時にCommitしている) 'MyRs.Open "TESTDB..TEST001",MyDB,adOpenStatic : MyRs2.Open "SELECT * FROM TESTDB..更新テスト",MyDB,adOpenKeyset,adLockPessimistic If Err <> 0 Then 'Error処理 End If If MyRs2.EOF Then MyRs2.AddNew MyRs2![FLD1] = MyRs2![FLD1A] Else MyRs2![FLD1] = "TEST" End If MyRs2.UpDate 'ここは正常終了。(Err = 0) 'テスト用にエラー設定 Err = 1 if Err <> 0 then '(B)不具合発生パターンの場合、ROLLBACK をしても、DBに登録されてしまう。 MyDB.Execute "ROLLBACK TRANSACTION TEST999",,adCmdText+adExecuteNoRecords Exit Function End If MyRs.Close MyRs2.Close SmileDB.Execute "COMMIT TRANSACTION TEST999",,adCmdText+adExecuteNoRecords End Function

  • ActiveX DLLでのオラクルのトランザクション

    VB6とOracle9iのOO4Oにてシステムを構築しておりますが、一つ解らないことがありましたので、どなたかご教授願います。 あるPG(通常のEXEです)よりActiveX DLLを呼び出してOracleの表へデータを挿入する処理があります。呼び出し元となる通常のEXEはまずOracleの接続処理を記述しています。正常に接続が完了したならトランザクションを開始し、表のDeleteを実行します。その後ActiveX DLLを呼び出して表のInsertを実行しています。再び通常のEXEに制御が戻り、トランザクションの完了(COMMIT)または破棄(ROLLBACK)を行います。しかし、最後のトランザクションのCOMMIT(ROLLBACK)を行うと『コッミト(ロールバック)時にアクティブなトランザクションがありません』というエラーが発生してしまいます。正しくBegin Transactionを実行しているのに、これはどういうこと何のでしょうか。ご存知の方がいらっしゃましたら教えてください。

  • SQL実行エラー時のロールバックについて

    クエリアナライザを使用し、以下のような複数のステートメントを実行するクエリを流します。 「BEGIN TRANSACTION TRAN_X INSERT文1; INSERT文2; UPDATE文3; …」 最終的に成功したら commit、途中でエラーが出たらrollbackしたいと考えています。 @@ERRORでなくJAVAでいう「try~catch」またはVBでいう「ON ERROR」構文のようなものはないのでしょうか? どなたかご教授お願いします。

  • AccessShareLock はどの程度気にする必要がある?

    PostgreSQL8.2とJavaを使ったWebアプリケーションを構築しています。 pgAdminでサーバー状態>ロック で参照してみたところ、AccessShareLockというのが大量に発生していました。 マニュアルを参照してみたところ、 >AccessShareLock を除き,トランザクション内で獲得されたすべての ロックモードは,そのトランザクション実行の間維持されます. とあり、つまりAccessShareLockはトランザクションの間でも維持されないということだと思うのですが、どうも解放されてはいないようです。 これは通常の(つまり、更新しない)select文を発行したときに発生するロックだと思うのですが、いろいろ調べても、どうもこのAccessShareLockというのをどのくらい気にしたらいいのかがわかりません。 このロックが残っていると、どのようなときに困るでしょうか。 また、解放するためには通常のselectのあとでもcommit(またはrollback)をする必要があるということになるでしょうか。その際にはcommitとrollback、どちらがいいということはあるでしょうか。 ご存じのかたがいらっしゃいましたらご教示いただければと思います。よろしくお願いいたします。

専門家に質問してみよう