当我使用PHP从资源(查询)中获取行时,我得到了一个非常奇怪,毫无意义和完全随机的错误。
我的开发机器是Windows XP SP3与Apache 2.2,而MySQL运行在虚拟机上,使用Ubuntu 10.04,768 MB的RAM,100 GB的HDD和4个逻辑核心(Intel q6600)。然而,这个问题与Windows上的PHP无关,因为当我在数据库机器上运行代码时,我得到了相同的错误。
我正在使用mysql
扩展(不是mysqli
或mysqlnd
),但环顾四周,我发现了一个关于mysqlnd扩展相关错误的补丁,所以,也许,我应该试试。
主要问题是当我执行这个查询时(一个非常大的查询,有几个派生表和20多个连接),处理结果很快,一切都很顺利,但是当我的代码花了大约15/20秒来处理一个行块时(我需要从一个以非常特定的方式链接的行块中构建一个对象,我不能改变这一点,数据库不是我的,并从这个对象制作一些PDF)一段时间后(随机时间)我得到这个错误“空行包体”。
我使用无缓冲查询来减少内存消耗(如果启用缓冲,我会使用大约260 MB的内存),但这不应该是问题所在。
8条答案
按热度按时间r6vfmomb1#
我遇到了同样的错误。我正在使用PDO,但基本上应该是一样的。
您是否在MyISAM表上操作?如果是,问题可能与此Engine使用的锁定模型有关:它锁定整个表,对于阅读使用共享锁,对于写入使用排他锁。
这就是我想做的读取一个无缓冲的大结果集,并更新同一个表中的一些行。由于在同一个连接上不能发出一条语句,而它持有一个无缓冲的结果集,我尝试使用另一个连接进行更新。阅读一直很顺利,直到第一次更新,在这一点上脚本停顿了大约一分钟,然后我得到了“空行包体”错误。
你看,当阅读无缓冲时,共享锁会一直保持,直到整个结果集被读取或游标被关闭。在此期间,表被共享锁锁定,因此其他连接可以获得表上的共享锁(换句话说,从表中读取),但独占锁(用于写入)必须等待。如果在同一脚本中发生这种情况,它将死锁。
现在,为了防止无休止的死锁,MySQL将在一段时间后强制释放您的共享锁(IIRC这受table_lock_wait_timeout值的影响),转储您的结果集并允许具有等待排他锁的写入语句轮到它。
因此,虽然在我的例子中,是同一个脚本执行了此操作,因此在超时到期之前一直处于停滞状态,但也可能是其他脚本正在尝试对表执行具有相同效果的写操作,这可能就是您的例子中发生的情况。
对我来说,解决问题的方法是将表类型更改为InnoDB,因为该引擎使用行级锁而不是表级锁。然而,由于您说数据库不是您的,这对您来说可能不可能。
sbtkgmzw2#
实际的问题是PHP和MySQL之间的连接中断(=在PHP * 接收 * 所有数据之前停止)。
当PHP(PDO)执行MySQL查询时,它在打开的连接上发送查询,然后等待响应。响应由一组头和一个主体组成,有点像HTTP请求。
如果连接中断,而PDO没有收到所有的头,那么你会得到一个警告“错误阅读结果集的头”,这意味着PDO不能解释响应,因为它只是部分(头)。
如果在解析包体时连接断开,那么PDO将产生一个“空行包体”,对应于您的错误。有关其他信息,请参阅this Github PR
因此,解决方法是找出连接被终止的原因:
qc6wkl3g3#
不久前出现了这个错误,我通过增加
当一个连接在写入时打开,等待另一个查询结束以继续插入,这会超时,给出一个空行包。我正在处理非常大的数据集,使用的值超过360。您的值将取决于您的用例。
pod7payv4#
user589182的答案是正确的。我正在做本质上相同的事情:从同一个PHP脚本中读取一个无缓冲的大型结果集,并更新同一个表中的一些行。在大约2500次更新后,我得到了完全相同的错误消息。从MyISAM切换到InnoDB后,问题解决了。
ep6jt1vc5#
我得到了同样的错误,而且在更新同一个表的行时,我也在阅读一个未缓冲的大型结果集。
与其切换到InnoDB,一个更好的解决方案可能是创建一个临时表,只包含原始表的主键。然后,在该临时表中循环,同时从原始表中每次选择和更新一行。您必须使用两个单独的MySQL连接才能完成此操作,否则您将获得“Commands out of sync”错误。
您可能需要锁定原始表,以防止其他任何人在此过程中对其进行阅读/写。
5rgfhyps6#
我在InnoDB上从来没有遇到过这种类型的问题,直到我切换了编码环境(字面上的意思,就像位置)。所以,如果你改变了你的无线连接,这可能是问题,特别是如果它是一个公共场所。
wj8zmpe17#
我现在遇到了同样的问题,阅读巨大的无缓冲查询。所有的表都是InnoDB的。
当另一个进程启动
mysqldump
时,它就停止了。所以这可能也是原因。sczxawaw8#
我的“身体中的空行包”和其他一些相关的随机错误是由网络路由器引起的。
通过绕过路由器,直接连接到互联网,我没有更多像这样的奇怪错误。