Php MySQL没有正确选择行(有时)

Php MySQL没有正确选择行(有时),php,mysql,innodb,Php,Mysql,Innodb,这是对这个问题的一个更新,我一直在想到底发生了什么: 我最终接受了一个答案,因为它确实回答了我提出的问题(“为什么会发生这种情况”),尽管它没有回答我真正想知道的问题(“为什么会发生在我身上”)但是关于后一个问题,我已经设法缩小了范围,我想我可以肯定地说,有些事情是错的,我不理解,也从未见过 这个问题真的很难调试,因为出于我无法理解的原因,登录数据库会自动修复它。然而,今天我在终端中打开MySQL会话时成功触发了问题状态。以下是从该会话中获取的一些查询和后续响应: 首先,这是我的表格布局: m

这是对这个问题的一个更新,我一直在想到底发生了什么:

我最终接受了一个答案,因为它确实回答了我提出的问题(“为什么会发生这种情况”),尽管它没有回答我真正想知道的问题(“为什么会发生在我身上”)但是关于后一个问题,我已经设法缩小了范围,我想我可以肯定地说,有些事情是错的,我不理解,也从未见过

这个问题真的很难调试,因为出于我无法理解的原因,登录数据库会自动修复它。然而,今天我在终端中打开MySQL会话时成功触发了问题状态。以下是从该会话中获取的一些查询和后续响应:

首先,这是我的表格布局:

mysql> describe forum_posts;                                                    
+-----------+------------+------+-----+---------+----------------+
| Field     | Type       | Null | Key | Default | Extra          |
+-----------+------------+------+-----+---------+----------------+
| post_id   | int(11)    | NO   | PRI | NULL    | auto_increment |
| thread_id | int(11)    | YES  | MUL | NULL    |                |
| forum_id  | int(11)    | YES  | MUL | NULL    |                |
| user_id   | int(11)    | YES  | MUL | NULL    |                |
| moderator | tinyint(1) | NO   |     | 0       |                |
| message   | mediumtext | YES  | MUL | NULL    |                |
| date      | int(11)    | NO   | MUL | NULL    |                |
| edited    | int(11)    | YES  |     | NULL    |                |
| deleted   | tinyint(1) | YES  | MUL | 0       |                |
| bbcode    | tinyint(1) | NO   |     | 1       |                |
+-----------+------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
现在,让我们看看给定论坛帖子中有多少帖子:

mysql> SELECT count(post_id) as num FROM `forum_posts` where thread_id=5243;
+-----+
| num |
+-----+
| 195 |
+-----+
1 row in set (0.00 sec)
好的,但我只想要没有设置
deleted
标志的论坛帖子:

mysql> SELECT count(post_id) as num FROM `forum_posts` where thread_id=5243 and deleted=0;
+-----+
| num |
+-----+
|   0 |
+-----+
1 row in set (0.06 sec)

mysql> select post_id,deleted from forum_posts where thread_id=5243 and deleted=0;
Empty set (0.06 sec)
好的,让我们加倍确保它们实际上没有全部删除:

mysql> select post_id,deleted from forum_posts where thread_id=5243;
+---------+---------+
| post_id | deleted |
+---------+---------+
|  104081 |       0 |
|  104082 |       0 |

[snip]

|  121162 |       0 |
|  121594 |       0 |
+---------+---------+
195 rows in set (0.00 sec)
该表中的每一行都将“deleted”设置为0,但将
和deleted=0添加到查询中不会产生任何结果。直到我通过从终端窗口再次登录MySQL打开一个新会话,之后我可以再次正确地选择“deleted”为0的行

到底是什么


更新:

@miken32在下面的评论中建议我尝试
解释选择…
,因此:

mysql> explain select post_id,deleted from forum_posts where thread_id='5243' and deleted=0;
+----+-------------+-------------+-------------+-------------------+-------------------+---------+------+------+--------------------------------------------------------------+
| id | select_type | table       | type        | possible_keys     | key               | key_len | ref  | rows | Extra                                                        |
+----+-------------+-------------+-------------+-------------------+-------------------+---------+------+------+--------------------------------------------------------------+
|  1 | SIMPLE      | forum_posts | index_merge | thread_id,deleted | thread_id,deleted | 5,2     | NULL |   97 | Using intersect(thread_id,deleted); Using where; Using index |
+----+-------------+-------------+-------------+-------------------+-------------------+---------+------+------+--------------------------------------------------------------+
1 row in set (0.00 sec)

根据使用FORCE键改变查询结果的评论,我们很可能正在处理合并优化器错误。原始查询的解释显示优化是通过从已删除的键中选择,然后从post_id键中选择,然后合并结果来完成的。当我们强制绕过该代码时,问题就消失了

从这一点出发的步骤是:

  • 使用最新5.6版本的MySQL在相同的数据上进行尝试
  • 如果问题再次出现,尝试将其隔离到最小的测试用例中,访问并报告错误

    • 驱除守护进程和幽灵!添加此索引以避免任何“合并”错误:

      旗帜上的索引几乎总是无用的。这次比没用还糟


      这将比FORCE INDEX更便宜、更快、更安全。

      您的服务器最近是否被恶魔、鬼魂或其他超凡生物占用?据我所知,不是这样。而且它似乎也不是特定于平台的。我在运行Debian Wheezy的生产服务器和运行Debian sid的代码和数据库副本(通过mysqldump复制)的本地笔记本电脑上都复制了此错误。尝试转储可能是因为索引已损坏。尝试删除已删除的索引并重新创建它。解释显示它正在使用索引扫描。另外,尝试
      select count(*)
      而不是
      select count(post\u id)
      。MySQL有时有一些其他数据库不具备的“功能”。在出现问题的两个系统上,MySQL的版本是什么?就我的应用程序而言,仅在生产中使用
      force key
      是合理的修复方案吗?或者这只是“掩盖”了一个我还没有发现的可能更糟糕的问题?如果这确实是一个合并优化器错误,那么它可能会影响到命中相同代码路径的其他查询。所以我会努力解决这个问题。此外,它是MySQL社区的一项服务,有助于使MySQL变得更好。哦,我不是建议我不报告它,我将努力找出触发它的确切方法(我在这方面也取得了一些进展)。我只是想知道,在不久的将来,我是否应该完全删除那些似乎会加剧问题的代码路径,而不是仅仅在受影响的查询上强制使用密钥
      INDEX(deleted, thread_id)  and DROP the key on just deleted