Some MySql queries with PHP condition

2019-07-18 02:33发布

background: I want to match users in a PHP-Webapp. When an user enters a specific page, he will be put into a virtual pool. The pool is realised as the following MySql table:

"search-table": id|userId|parameter

Every user is checking, if there is annother user in that table, who is ready to match.(ready to match=same parameter). The check is done by an AJAX-Request to my PHP controller every x-seconds. (the AJAX-Request ist repeated until a match was found, or the user leaves).

If this query returns a valid partner userId, annother query should excecute an INSERT to a second table.

"matching-table": id|firstUser|secondUser

After inserting, both "search-table" entries for the matched users should be deleted.

How can guarantee, that there will not be "two Inserts for the same user", because some users are performing the "Check" query at the same time? ->race condition.

For example: UserA, userB and UserC are in the "search-table". -UserA: his AJAX-request returns UserC -UserB: his AJAX-request returns also userC

-UserA: creates insert into "matching-table" with firstUser=UserA and secondUser=UserC -UserB: also creates an insert into "matching-table", but with firstUser=UserB and secondUser=UserC -UserA: deletes "search-table" entries with "userA" and "userC"

=> UserB should not be able to create the INSERT, because UserA already picked UserC.

How can i realise that? My actual code is:

try
{   
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->beginTransaction();   

    $stmt =  $dbh->prepare("SELECT id FROM [...]");

    $stmt->bindParam(1, [...]);

    if($stmt->execute())
    {
        if($row = $stmt->fetch())
        {
            $matchID = $row['id'];
            //check if parameter/id is ok
            $checkD = $this->checkId($matchID);

            if($checkD)
            {
                return '-1';
            }
            else
            {      

                //Create entry in "matching-table"
                $stmt = $dbh->prepare("INSERT INTO [...]");

                $stmt->bindParam(1,[...]);
                $stmt->execute();

                //Delete Users from "serach-table"
                $stmt = $dbh->prepare("DELETE [...]");

                $stmt->bindParam(1,[...]);
                $stmt->execute();

                $dbh->commit();

                return $matchID;                            
            }
        }
        else
        {
            return '-1';
        }
    }
    else
    {
        return '-1';
    }       
} catch(Exception $e)
{
    $dbh->rollBack();
    return '-1';
}

How can i "lock" the table, when a user gets an valid result from "search-table" and he wants to create the "matching-table" entry - so no other user can create that entry also?

0条回答
登录 后发表回答