Странная ошибка MySQL «Пустое тело пакета строки» при использовании mysql_fetch_object (PHP 5.3.3) - PullRequest
8 голосов
/ 23 сентября 2010

Я получаю действительно странную, бессмысленную и совершенно случайную ошибку, когда выбираю строки из ресурса (запроса) с использованием PHP.

Моя машина для разработки - Windows XP SP3 с Apache 2.2, в то время как MySQL работает на виртуальной машине, используя Ubuntu 10.04, с 768 МБ оперативной памяти, 100 ГБ жесткого диска и 4 логическими ядрами (Intel q6600). Однако эта проблема не связана с PHP в Windows, потому что я получаю ту же ошибку при запуске кода на компьютере базы данных.

Я использую расширение mysql (не mysqli или mysqlnd), но, оглядываясь по сторонам, я нашел патч, касающийся этой ошибки, связанной с расширением mysqlnd, поэтому, вероятно, я должен попробовать.

Основная проблема заключается в том, что когда я выполняю этот запрос (действительно большой запрос с парой производных таблиц и более чем 20 объединениями) и обрабатывает результаты быстро, и все идет хорошо, но когда мой код потратил около 15/20 секунд, чтобы обработать блок строк (мне нужно построить объект из блока строк, связанных между собой действительно определенным образом, я не могу это изменить, база данных не моя, и сделать несколько PDF из этого объекта) через некоторое время ( случайное время) Я получаю эту ошибку "Пустое тело пакета строки".

Я использую небуферизованные запросы для уменьшения потребления памяти (если я включаю буферизацию, я получаю около 260 МБ используемой памяти), но это не должно быть проблемой.

Ответы [ 6 ]

18 голосов
/ 25 января 2011

Я столкнулся с той же ошибкой. Я использовал PDO, но это должно быть одно и то же.

Вы работаете за столом MyISAM? Если это так, то проблема, вероятно, связана с моделью блокировки, которую использует этот Engine: он блокирует всю таблицу, для чтения с общей блокировкой, для записи с эксклюзивной блокировкой.

Вот что я пытался сделать: прочитать большой набор результатов без буферизации и обновить некоторые строки в той же таблице. Поскольку вы не можете выполнить оператор для того же соединения, пока он содержит небуферизованный набор результатов, я попытался использовать другое соединение для обновлений. Чтение шло хорошо до первого обновления, после чего сценарий останавливался примерно на минуту, затем я получил ошибку «Пустое тело пакета строк».

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

Теперь, чтобы предотвратить бесконечную взаимоблокировку, MySQL через некоторое время принудительно снимет вашу общую блокировку (IIRC на это влияет значение table_lock_wait_timeout), выгрузив ваш набор результатов и позволив оператору write с ожидающей эксклюзивной блокировкой получить свою очередь .

Итак, хотя в моем случае это был тот же сценарий, который делал это и, следовательно, зависал до истечения времени ожидания, возможно, что какой-то другой сценарий пытается выполнить операцию записи в таблицу с тем же эффектом, что, вероятно, случилось в вашем случае.

Что решило проблему для меня, так это изменив тип таблицы на InnoDB, поскольку этот движок использует блокировки на уровне строк вместо блокировок на уровне таблиц. Однако, поскольку вы говорите, что база данных не ваша, это может оказаться невозможным для вас.

6 голосов
/ 08 ноября 2017

Имея эту ошибку некоторое время назад, я исправил ее, увеличив значение

net_read_timeout = 360
net_write_timeout = 360

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

0 голосов
/ 14 октября 2018

У меня сейчас та же проблема, я читаю огромный небуферизованный запрос.Все таблицы InnoDB.

И он останавливается, когда запускается другой процесс mysqldump.Так что это также может быть причиной.

0 голосов
/ 07 мая 2016

Я был на InnoDB и никогда не сталкивался с подобными проблемами, пока не переключил среду программирования (буквально, как местоположение). Таким образом, если вы изменили беспроводное соединение, это может быть проблемой, особенно если это публичное место.

0 голосов
/ 17 октября 2012

Я получил ту же ошибку, и я также читал большой набор результатов без буферизации при обновлении строк той же таблицы.

Вместо переключения на InnoDB, лучшим решением может быть создание временной таблицы, содержащей только первичный ключ исходной таблицы. Затем переберите эту временную таблицу, выбирая и обновляя по одной строке за раз из исходной таблицы. Для этого вам придется использовать два отдельных соединения MySQL, в противном случае вы получите ошибку «Команды не синхронизированы».

Возможно, вам придется заблокировать исходную таблицу, чтобы никто не мог читать / писать в нее, пока это происходит.

0 голосов
/ 07 марта 2011

user589182 ответ на месте.По сути, я делаю одно и то же: читаю большой набор результатов без буферизации и обновляю некоторые строки в той же таблице из того же PHP-скрипта.Я получил точно такое же сообщение об ошибке после прибл.2500 обновлений.Проблема решена после переключения с MyISAM на InnoDB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...