3

PHP+MySQLを実行しているWebサイトがあります。これはマルチユーザーシステムであり、ほとんどのMySQLテーブルはMyISAMベースです。

次の状況で、ここ数時間困惑しました。2人の(同時)ユーザーA、Bがいます。それらの両方がこれを行います:

  1. 表1で読み取り操作を実行します
  2. 別のテーブル2で書き込み操作を実行します(前の読み取り操作が明確な結果を返す場合のみ、たとえばSTATUS = "OK")

BはAに向かって少し遅れています。

したがって、次のように発生します。

  • ユーザーAは、表1で読み取りを実行し、STATUS="OK"を確認します。
  • (ユーザーAのスケジュールは表2に書き込みます)
  • ユーザーBは、表1で読み取りを実行し、それでもSTATUS="OK"を表示します。
  • ユーザーAが表2に書き込みを実行します(結果としてSTATUS = "NOT OK"になります)
  • ユーザーBは、表2で書き込みを実行します(STATUS = "OK"と想定)

表1の読み取りと表2への書き込みがクリティカルセクションとして定義され、アトミックに実行される場合、これを防ぐことができると思います。これは、スレッドなどを使用するJavaでは完全に正常に機能することを私は知っていますが、PHPでは、私が知る限り、スレッド通信はありません。

ですから、私の問題の解決策はデータベースに関連している必要がありますよね?何か案は?

どうもありがとう!

4

1 に答える 1

3

正しい方法: InnoDBとトランザクションを使用します。

間違った方法:データベース操作を実行する前に、GET_LOCK() MySQL関数を使用して排他的な名前付きロックを取得します。ドンになったら、RELEASE_LOCK()でロックを解除します。特定のロックを所有できるのは1つのクライアントのみであるため、これにより、「クリティカルセクション」に同時に複数のスクリプトインスタンスが存在することはありません。

擬似コード:

SELECT GET_LOCK('mylock', 10);
If the query returned "1":
    //Read from Table 1
    //Update Table 2
    SELECT RELEASE_LOCK('mylock');
Else:
    //Another instance has been holding the lock for > 10 seconds...
于 2012-08-19T14:26:16.127 に答える