возможно ли создать дубликат ip в этом коде?

У меня есть ротатор всплывающих окон, который подсчитывает ip пользователя unic пользователя в день (для дубликатов в тот же день не разрешен IP-адрес дубликата)

$userip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']); $date = date('Ym-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** } 

выше код является примером. Я знаю полный код.

но когда я смотрю на свою таблицу popupip phpmyadmin, есть несколько дубликатов ip для пользователя (тот же самый ip-адрес для пользователя в ту же дату)

как это возможно?

Дополнительная информация: в popupip userid есть int (11), date – «тип даты, такой как 2014-05-30», а ip – varchar. эта страница может открываться «как можно быстрее в одно и то же время» по всплывающим страницам. существует ли связь между быстрым открытием страницы в одно и то же время пользователем и дублированием создания ip? есть ли ошибка в MySQL? (может быть, большая ошибка !!!!)

Да, это возможно. Это классический случай состояния гонки.

Краткое объяснение:

Существует вероятность того, что 2 запроса одновременно пройдут первую проверку, получите $num == 0 и оба вставляют новую строку.

Чтобы устранить это, вам необходимо создать ограничение UNIQUE которое охватывает (user_id, ip, date) столбцы

Длительное объяснение:

  • Википедия – Состояние гонки
  • Stackoverflow – Что такое состояние гонки?

Если несколько запросов поступают из одного и того же ip одновременно, возможно, что некоторые из них выполняют запрос выбора, прежде чем какой-либо из них выполнит запрос на вставку (в результате получится несколько вставок с тем же ip и датой).

Решением для этого является создание индекса UNIQUE с ip, user_id и датой (вы можете легко сделать это в phpMyAdmin, выполнив запрос ниже):

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

После этого вы можете оптимизировать свой код и просто выполнить запрос «INSERT IGNORE», который только вставляет, если комбинация (ip, user_id, date) еще не существует в таблице:

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

С помощью этого решения вам не нужно делать дополнительный запрос «SELECT» или «if», чтобы проверить, есть ли результаты.