4

PHP 5.4.0 アプリケーション (IIS、FastCGI、非スレッドセーフ) で、2 人がデータベース内の同じテーブルをまったく同時に同じコードを実行して更新し、うっかりお互いのデータを台無しにしてしまう可能性はありますか?

私が質問する理由は、説明のつかないデータの不具合が時折見られるためです。最近のケースでは、別の顧客が同じテーブルをまったく同時に更新したことがわかりました。

私の質問のパート 2 は、これが実際に起こっている場合、どうすれば防止できるのでしょうか?

4

2 に答える 2

3

トランザクションを使用せずに各リクエストで複数の SQL ステートメントを実行している場合、その可能性は非常に高くなります。SQL ステートメントはアトミックであり、トランザクション ラップされた一連のステートメントと同様に、「グリッチ」が発生することはありません。

また、SQL 以外の場所 (フラット ファイルなど) で異なるリクエスト間で状態を共有している場合、控えめに言っても、明らかにスレッド セーフが損なわれます。

パート 2: トランザクションを使用する :)

于 2012-12-05T00:16:29.437 に答える
2

PHP がスレッドセーフでないため、「お互いのデータを台無しにする」ことはできません。Apache の設定を準備/作成している場合 (例: を使用SetLocale)、または共有情報を同時に更新するようにプログラムしている場合 (例: フラットファイル、アマダムが言うように)。

MySQL などのほとんどの通常のプロセス、GET パラメータの読み取りなどは影響を受けません。

したがって、問題がロケールにない限り、それはスレッド設定ではなくコードになります。

SetLocale を使用している場合、トランザクションやその他のメソッドは何の違いもありません。ラウンドをプログラムできる他のもの。


並行アクション用にプログラムしていない場合、データを台無しにする可能性があります。これは、スレッド セーフでも非スレッド セーフでも発生する可能性があります。「スレッドセーフ」であっても、異なる速度と順序で並行スレッドを処理できることに注意してください。

以下は危険な例です。

  • ステートメント a) テーブルを読み取って次の更新値を取得する
  • ステートメント b) 前の値を使用してテーブルに書き込む
  • ステートメント c) 次のユーザーのために「次の更新」テーブルを更新します。

ステートメントは、「ユーザー 1」がすべてを実行し、その後に「ユーザー 2」が続くことで処理できます (理想的で、どのようにプログラムしたか)。しかし同様に、「ユーザー 1」が「a」と「b」を実行し、続いて「ユーザー 2」がすべてを実行し、次に「ユーザー 1」が「c」を実行します。この場合、「ユーザー 2」は「ユーザー 1」を上書きします。 " 書きました。

(繰り返しますが、これは PHP の「非スレッドセーフ」とは関係ありません。)

この後者の問題を回避する方法:

  1. トランザクションが役立つ場合があります。「WITH CONSISTENT SNAPSHOT」オプションを使用しない限り、上記の例では実際には役に立ちません。コミットを遅らせるだけで、ステートメント「a」で値を読みすぎたからです。
  2. テーブル ロックを使用すると、ユーザーによるテーブルへの読み取りまたは書き込みを防止できます。したがって、上記の例では、最初に「更新」テーブルをロックし、トランザクションを実行してからロックを解放します。これにより、2 番目のユーザーは、「ユーザー 1」がロットを完了するまで待ってから番号を読み取ることになります。
  3. 「AUTO INCREMENT」主キー、または「INSERT INTO... ON DUPLICATE KEY」や「REPLACE」などのコードを含む mySQL の機能を使用します。

可能であれば、3 番目のオプションが最適です。テーブルのロックが乱雑になり、トランザクションが問題を解決しないことがあります。

于 2012-12-05T00:54:47.113 に答える