0

私は現在、次のルールでインスタント勝利ゲームを作成しています。最後のユーザーが勝利した後、少なくとも30分後に登録した最初のユーザーです。したがって、ユーザーは 30 分ごとに勝つことができます。数時間以内に誰も登録しない場合は、最初に登録した人が勝ちます。

サーバーは PHP 5.2.0 を使用しているため、DateTime クラスを使用していません。私のテーブルの勝者テーブルは InnoDB です。

私のスクリプトのこの部分は、ユーザー登録時に各クライアントによって呼び出され、ユーザーが勝ったかどうかを決定します。

$currentTime = date("Y-m-d H:i:s");

// We're looking for the last winner in the winners table
$res = $dbh->query("SELECT date FROM winnertable ORDER BY id DESC")->fetch(PDO::FETCH_ASSOC);

if(empty($res)){
    // If there is no last winner then the user wins
    $winner = true;
}else{
    // If there is already a last winner, we check the date of win, if superior to half an hour, the user wins 
    if(strtotime($currentTime)-strtotime($res["date"])>=1800){
        // Last winner was half an hour ago : winner
        $winner = true;
    }
}

// if the winner flag is set to true, add the user id to the winners table along with the date of winning
if($winner){
    $dbh->query("INSERT INTO winnertable (id_main, date) VALUES ('".$_SESSION['id']."', '".$currentTime."')");
}

次のページでは、ユーザーが勝ったかどうかがわかるように結果を表示する必要があります。なので後から決めるCRONジョブが作れません。

このスクリプトには欠陥があります。複数のクライアントがまったく同時にアクセスすると、おそらく複数のクライアントが勝利する可能性があるからです。

私はいくつかの解決策を読みました:

  • ロックの使用: しかし、パフォーマンス コストはわかりません。また、MyIsam テーブルはテーブル全体をロックし、InnoDB テーブルは更新用にマークされた選択された行のみをロックすることを読みました。そして、私はそこから何をすべきかわかりません。
  • 私の「日付」列を UNIQUE にすることで、同じ日付の複数の挿入を防ぐ必要があり、エレガントな回避策のように思えますが、信頼するには少し簡単すぎるようです。あなたのアドバイスが本当に欲しいです.
4

2 に答える 2

0

私は最終的に問題を別の方法で考えることに決め、解決策を投稿することにしました。

InnoDB テーブルの行レベル ロックを読み、次のことを行いました。

Stmt #1 : UPDATE Winnertable SET id_main=[id] WHERE date_add(next_date, INTERVAL X SECOND) < NOW() AND id_main = 0

PDO が変更された行 ($stmt->rowCount()) を返す場合、それが勝者であり、次の勝者のために勝者テーブルに新しい行を挿入する必要があります。

Stmt #2 (条件付き) : INSERT INTO Winnertable SET next_date=NOW()

助けてくれてありがとう!

于 2013-10-10T12:56:39.197 に答える
0

できることは、状況にさらにステージを追加することです。これにより、「潜在的な」勝者 (勝者の基準を満たすもの) を格納する別の一時テーブルが作成されます。次に、日付順のセカンダリ アクションとして SELECT を実行し、インデックスを昇順で 1 つに制限します。その値を取得して実際の勝者テーブルに追加し、それを次の勝利計算の基礎として使用して、一時テーブルをクリアします。そうすれば、勝者は1人だけになるはずです。もちろん、オーバーヘッドが追加されますが、それが発生するのは 30 分ごとになるため、あまり問題になることはないと思います。

于 2013-09-26T17:48:24.197 に答える