is it possible creation of duplicate ip in this co

2019-04-17 06:30发布

问题:

I have a popup rotator that count unic user's ip per day(NO duplicate ip is allowed for user in same date)

$userip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
$date = date('Y-m-d');
$result = mysql_query("SELECT `ip` FROM  `popupip` where ip = '$userip' AND userid = $secid AND date='$date'");
$num = mysql_num_rows($result);
    if ($num > 0) {
    // **it is duplicate Do not insert it in popupip table**
    }else{
    // **it is not duplicate ip insert it in popupip table**
    }

above code is an example.I know full code.

but when I look to my phpmyadmin popupip table there is a few duplicate ip for user (the exact same ip address for the user on the same date)

how is it possible?

extra information: in popupip userid is int(11) , date is "date type like 2014-05-30" and ip is varchar. this page may opens "as fast as possible at the same time" by popup pages. is there a relation between openning a page fast at same time by a user and duplicate ip creation? is there a bug in MySQL? (maybe a big bug!!!!)

回答1:

Yes, it is possible. It's a classical case of a race condition.

The quick explanation:

There is a chance that 2 requests simultaneously pass the first check, get $num == 0 and both insert a new row.

To eliminate it you need to create a UNIQUE constraint that covers (user_id, ip, date) columns

The long explanation:

  • Wikipedia - Race Condition
  • Stackoverflow - What is a race condition?


回答2:

If multiple requests are coming from the same ip at the same time, it is possible that a few of them are executing the select query before any of them executes the insert query (resulting in multiple inserts with the same ip and date).

A solution for this is to create a UNIQUE index with ip, user_id and date (you can easily do this in phpMyAdmin by running the query below):

ALTER TABLE `popupip` ADD UNIQUE (`ip`, `user_id`, `date`);

After that you can optimize your code and simply execute an "INSERT IGNORE" query that only inserts if the combination (ip, user_id, date) doesn't already exist in the table:

mysql_query("INSERT IGNORE INTO `popupip` (`ip`, `user_id`, `date`) VALUES ('$userip', $secid, '$date');");

With this solution you don't need to do the extra "SELECT" query, or the "if" to check if there are results.