Почему наши запросы застряли в состоянии "Запись в сеть" в MySql?

У нас много запросов

select * from tbl_message

которые застревают на состоянии "Запись в сеть". Таблица имеет 98 тысяч строк.

Дело в том, что... мы даже не выполняем ни одного запроса из нашего приложения, поэтому я думаю, что вопрос заключается в следующем:

  • Что может генерировать запрос?
  • ... и почему он застревает в состоянии "запись в сеть"

Я чувствую себя глупо, задавая этот вопрос, но я на 99,99% уверен, что наше приложение не выполняет такой запрос к нашей базе данных... однако мы выполняем пару запросов к этой таблице, используя инструкцию WHERE:

 SELECT Count(*) as StrCount FROM tbl_message WHERE m_to=1960412 AND m_restid=948

 SELECT Count(m_id) AS NrUnreadMail FROM tbl_message WHERE m_to=2019422 AND m_restid=440 AND m_read=1

 SELECT * FROM tbl_message WHERE m_to=2036390 AND m_restid=994 ORDER BY m_id DESC

Я искал наше приложение несколько раз для select * from tbl_message но ничего не нашли... Но все равно наш журнал запросов на нашем сервере MySQL полон Select * from tbl_message запросы

3 ответа

Решение

Поскольку приложения волшебным образом не генерируют запросы так, как им нравится, я думаю, что вполне вероятно, что где-то в вашем приложении есть ошибка, которая вызывает это. Вот несколько советов, которые вы можете использовать, чтобы отследить это. Я предполагаю, что вы используете PHP, так как вы используете MySQL, поэтому я буду использовать это для моих примеров.

Попробуйте добавить комментарии перед всеми вашими запросами в приложении, например так:

$sqlSelect  = "/* file.php, class::method() */";
$sqlSelect .= "SELECT * FROM foo ";
$sqlSelect .= "WHERE criteria";

Комментарий появится в вашем журнале запросов. Если вы используете какую-то оболочку API базы данных, вы можете добавить эти сообщения автоматически:

function query($sql)
{
    $backtrace = debug_backtrace();
    // The function that executed the query
    $prev = $backtrace[1];
    $newSql = sprintf("/* %s */ ", $prev["function"]);
    $newSql .= $sql;

    mysql_query($newSql) or handle_error();
}

Если вы не используете оболочку, а выполняете запросы напрямую, вы можете использовать расширение runkit и функцию runkit_function_rename, чтобы переименовать mysql_query (или что вы используете) и перехватить запросы.

Временно включить журнал запросов, поставив

log=

в ваш файл my.cnf перезапустите mysql и просмотрите журнал запросов для этих загадочных запросов (вам не нужно давать журналу имя, оно будет принимать одно из значений хоста).

Существует (по крайней мере) два режима извлечения данных для MySQL. С помощью c api вы можете либо вызвать mysql_store_result (), либо mysql_use_result ().
mysql_store_result () возвращается, когда все данные результатов передаются с сервера MySQL в память вашего процесса, т.е. никакие данные не должны передаваться для дальнейших вызовов mysql_fetch_row ().

Однако с помощью mysql_use_result () каждая запись должна выбираться индивидуально, если и когда вызывается mysql_fetch_row (). Если ваше приложение выполняет некоторые вычисления, которые занимают больше времени, чем период времени, указанный в net_write_timeout между двумя вызовами mysql_fetch_row (), сервер MySQL считает, что ваше соединение истекло.

Другие вопросы по тегам