У меня есть несколько открытых окон браузера, указывающих на ту же самую обновляющуюся страницу PHP. Он обращается к базе данных MySQL для идентификации устаревшей информации о клиентах. В частности, получение записей, которые не были обновлены в последний день и принудительно обновили. Остальная часть кода, похоже, отлично обрабатывается.
Вот мой запрос MySQLi:
$query = "SELECT * FROM customers WHERE customer_group='consumables' AND customer_updated < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY RAND() LIMIT 10";
Мне сообщили, что RAND () не очень подходит из-за медленной обработки больших таблиц, но мои таблицы не будут увеличиваться до более чем 20000 до конца этого проекта. У меня также есть случайная переменная, передаваемая по URL-адресу, например «clientdataupdates.php? Nocachepls = 1541231».
Итак, вот моя проблема: из текущих 5000 нечетных записей, если этот скрипт запускается в нескольких окнах обозревателя одновременно, они получают те же записи, что и MySQL. Разумеется, выбранная запись, по-видимому, выбирается случайным образом, но одна и та же запись возвращается во всех окнах, если запрос выполняется в одно и то же время.
Мои исследования были весьма ограничены тем фактом, что ключевые слова, которые я искал (в течение нескольких дней сейчас), по-видимому, относятся к другим проблемам, например: «php mysql возвращает тот же результат при использовании rand ()» имеет слишком много ответов Google, которые указывают к использованию rand () вообще.
Хотя я все равно буду признателен за любую помощь, я бы больше хотел узнать, почему это происходит. Мое знание внутренней работы MySQL ограничено, но для всего моего опыта взаимодействия с PHP и MySQL я не видел ничего подобного.
ОБНОВЛЕНО:
Я также проверил использование функции ajax, которая включает функцию обратного вызова, чтобы снова запустить ее. Каждый раз, когда содержимое div является одной и той же записью, но все равно выглядит, что выбранная запись произвольно.
<div id='worker1' class='workerDiv'>worker: waiting..</div> <div id='worker2' class='workerDiv'>worker: waiting..</div> <div id='worker3' class='workerDiv'>worker: waiting..</div> <div id='worker4' class='workerDiv'>worker: waiting..</div> <div id='worker5' class='workerDiv'>worker: waiting..</div> <script> function nextWorker(thisWorker){ setTimeout(function(){ ajaxpage('customerdata_worker.php',thisWorker,nextWorker(thisWorker)); }, 10000); } setTimeout(nextWorker('worker1'), 100); setTimeout(nextWorker('worker2'), 100); setTimeout(nextWorker('worker3'), 100); setTimeout(nextWorker('worker4'), 100); setTimeout(nextWorker('worker5'), 100); </script>
Вероятно, вы получаете информацию из кеша запросов MySQL в некоторых наборах результатов.
Попробуй это:
SELECT SQL_NO_CACHE * /* etc */
ОСТОРОЖНО: Поместите слово SQL_NO_CACHE в ту же строку, что и SELECT, и * (или имя первого столбца, который вы выбираете).
Смотрите это: http://dev.mysql.com/doc/refman/5.1/ru/query-cache.html В нем говорится:
Кэш запросов хранит текст инструкции SELECT вместе с соответствующим результатом, который был отправлен клиенту. Если идентичный оператор получен позже, сервер извлекает результаты из кеша запросов, а не анализирует и выполняет оператор снова. Кэш запросов распределяется между сеансами, поэтому набор результатов, сгенерированный одним клиентом, может быть отправлен в ответ на тот же запрос, выданный другим клиентом.
Pro tip: Избегайте SELECT *
в программном обеспечении. Укажите имена столбцов в наборе результатов.
MySQL использует системные часы для семени RAND()
когда нет второго значения. Начальное значение находится в микросекундах, и я не могу воспроизвести проблему RAND()
производя одно и то же значение дважды, как вы описываете.
Если вы открываете MySQL Workbench и одновременно выполняете два оператора. Выход для каждого отличается.
SELECT RAND(); SELECT RAND();
Когда вы открываете несколько вкладок и получаете одинаковые результаты. Вероятно, это проблема кэширования, но вы заявляете, что вы удаляете URL-адрес, чтобы предотвратить кеширование. Поэтому включите ведение журнала SQL на сервере и убедитесь, что вызываются новые запросы.
ORDER BY RAND()
медленный, потому что он требует, чтобы MySQL читал всю таблицу. Даже ORDER BY RAND() LIMIT 1
прежнему требует, чтобы MySQL читал всю таблицу.
ОБНОВИТЬ:
Вы можете увидеть, что такое случайное значение, которое генерирует SQL.
$query = "SELECT *, RAND() AS `X` FROM customers WHERE customer_group='consumables' AND customer_updated < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY `X` LIMIT 10";
Это будет включать столбец X
для каждой строки. Случайное значение, используемое для заказа запроса. Добавьте это к выходу и посмотрите, действительно ли каждый браузер возвращает одни и те же результирующие множества из MySQL.
Вы не ограничиваете количество записей, поэтому он только приносит разные заказы, но те же результаты, что и ваши места. Попробуйте ограничить свои результаты
$query = "SELECT * FROM customers WHERE customer_group='consumables' AND customer_updated < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY RAND() LIMIT 10";
Не совсем уверен, но поскольку у вас нет LIMIT в вашем запросе, я думаю, что может быть хорошей идеей удалить эту очень медленную часть ORDER BY RAND () из вашего запроса и просто использовать shuffle функции php в результате запроса mysql.