找回密码
 快速注册
搜索
查看: 81|回复: 19

今天凌晨开始出现奇怪的 Discuz! Database Error

[复制链接]

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

kuing 发表于 2024-8-12 14:25 |阅读模式
本帖最后由 kuing 于 2024-8-12 14:32 编辑 我啥也没改,就这样无端地,从今天凌晨开始,访问论坛首页就出现如下 Discuz! Database Error

PixPin_2024-08-12_14-15-48.png

(1104) The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
SELECT * FROM forum_thread WHERE tid>0 AND heats>=3 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 10


这个报错是这句查询的行数超过了 MAX_JOIN_SIZE 吗?
我在 myadmin 那里运行 SHOW VARIABLES LIKE 'max_join_size'; 查看 MAX_JOIN_SIZE 的值,显示是 4000000,这么大,也会超?咱这的帖数才几万呀😳

但如果直接访问帖子或者内部版块,又是可以正常看的。

我又注意到语句最后的 LIMIT 10 ,难道是首页那个四格?(每格显示 10 帖)?于是我进入后台关闭了首页四格,还真不报错了😳

一直都这样用的,怎么突然就出问题了呢?真奇怪……

@hbghlyj 帮我分析一下

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-12 16:52
本帖最后由 kuing 于 2024-8-12 17:25 编辑 @hbghlyj 别光点赞,帮我分析一下呗

首页四格的 html 代码在 template\default\forum\discuz.htm 里,不过应该无关。

关键应该是 source\module\forum\forum_index.php 里的这段:
  1. $grids = array();
  2. if($_G['setting']['grid']['showgrid']) {
  3.         loadcache('grids');
  4.         $cachelife = $_G['setting']['grid']['cachelife'] ? $_G['setting']['grid']['cachelife'] : 600;
  5.         $now = dgmdate(TIMESTAMP, lang('forum/misc', 'y_m_d')).' '.lang('forum/misc', 'week_'.dgmdate(TIMESTAMP, 'w'));
  6.         if(TIMESTAMP - $_G['cache']['grids']['cachetime'] < $cachelife) {
  7.                 $grids = $_G['cache']['grids'];
  8.         } else {
  9.                 $images = array();
  10.                 $_G['setting']['grid']['fids'] = in_array(0, $_G['setting']['grid']['fids']) ? 0 : $_G['setting']['grid']['fids'];
  11.                 if($_G['setting']['grid']['gridtype']) {
  12.                         $grids['digest'] = C::t('forum_thread')->fetch_all_for_guide('digest', 0, array(), 3, 0, 0, 10, $_G['setting']['grid']['fids']);
  13.                 } else {
  14.                         $images = C::t('forum_threadimage')->fetch_all_order_by_tid(10);
  15.                         foreach($images as $key => $value) {
  16.                                 $tids[$value['tid']] = $value['tid'];
  17.                         }
  18.                         $grids['image'] = C::t('forum_thread')->fetch_all_by_tid($tids);
  19.                 }
  20.                 $grids['newthread'] = C::t('forum_thread')->fetch_all_for_guide('newthread', 0, array(), 0, 0, 0, 10, $_G['setting']['grid']['fids']);
  21.                 $grids['newreply'] = C::t('forum_thread')->fetch_all_for_guide('reply', 0, array(), 0, 0, 0, 10, $_G['setting']['grid']['fids']);
  22.                 $grids['hot'] = C::t('forum_thread')->fetch_all_for_guide('hot', 0, array(), 3, 0, 0, 10, $_G['setting']['grid']['fids']);
  23.                 $_G['forum_colorarray'] = array('', '#EE1B2E', '#EE5023', '#996600', '#3C9D40', '#2897C5', '#2B65B7', '#8F2A90', '#EC1282');
  24.                 foreach($grids as $type => $gridthreads) {
  25.                         foreach($gridthreads as $key => $gridthread) {
  26.                                 $gridthread['dateline'] = str_replace('"', '\'', dgmdate($gridthread['dateline'], 'u', '9999', getglobal('setting/dateformat')));
  27.                                 $gridthread['lastpost'] = str_replace('"', '\'', dgmdate($gridthread['lastpost'], 'u', '9999', getglobal('setting/dateformat')));
  28.                                 if($gridthread['highlight'] && $_G['setting']['grid']['highlight']) {
  29.                                         $string = sprintf('%02d', $gridthread['highlight']);
  30.                                         $stylestr = sprintf('%03b', $string[0]);
  31.                                         $gridthread['highlight'] = ' style="';
  32.                                         $gridthread['highlight'] .= $stylestr[0] ? 'font-weight: bold;' : '';
  33.                                         $gridthread['highlight'] .= $stylestr[1] ? 'font-style: italic;' : '';
  34.                                         $gridthread['highlight'] .= $stylestr[2] ? 'text-decoration: underline;' : '';
  35.                                         $gridthread['highlight'] .= $string[1] ? 'color: '.$_G['forum_colorarray'][$string[1]] : '';
  36.                                         $gridthread['highlight'] .= '"';
  37.                                 } else {
  38.                                         $gridthread['highlight'] = '';
  39.                                 }
  40.                                 if($_G['setting']['grid']['textleng']) {
  41.                                         $gridthread['oldsubject'] = dhtmlspecialchars($gridthread['subject']);
  42.                                         $gridthread['subject'] = cutstr($gridthread['subject'], $_G['setting']['grid']['textleng']);
  43.                                 }
  44.                                 $grids[$type][$key] = $gridthread;
  45.                         }
  46.                 }
  47.                 if(!$_G['setting']['grid']['gridtype']) {
  48.                         $grids['slide'] = $focuspic = $focusurl = $focustext = array();
  49.                         $grids['focus'] = 'config=5|0xffffff|0x0099ff|50|0xffffff|0x0099ff|0x000000';
  50.                         foreach($grids['image'] as $ithread) {
  51.                                 if($ithread['displayorder'] < 0) {
  52.                                         continue;
  53.                                 }
  54.                                 if($images[$ithread['tid']]['remote']) {
  55.                                         $imageurl = $_G['setting']['ftp']['attachurl'].'forum/'.$images[$ithread['tid']]['attachment'];
  56.                                 } else {
  57.                                         $imageurl = $_G['setting']['attachurl'].'forum/'.$images[$ithread['tid']]['attachment'];
  58.                                 }
  59.                                 $grids['slide'][$ithread['tid']] = array(
  60.                                                 'image' => $imageurl,
  61.                                                 'url' => 'forum.php?mod=viewthread&tid='.$ithread['tid'],
  62.                                                 'subject' => addslashes($ithread['subject'])
  63.                                         );
  64.                         }
  65.                         $grids['slide'] = array_reverse($grids['slide'], true);
  66.                 }
  67.                 $grids['cachetime'] = TIMESTAMP;
  68.                 savecache('grids', $grids);
  69.         }
  70. }
复制代码

上面截图中 Debug 的第3点所在行就是这句:
  1.                 $grids['hot'] = C::t('forum_thread')->fetch_all_for_guide('hot', 0, array(), 3, 0, 0, 10, $_G['setting']['grid']['fids']);
复制代码

而 fetch_all_for_guide 的意思又得查到 source\class\table\table_forum_thread.php 里的这段:
  1.         public function fetch_all_for_guide($type, $limittid, $tids = array(), $heatslimit = 3, $dateline = 0, $start = 0, $limit = 600, $fids = 0) {
  2.                 switch ($type) {
  3.                         case 'hot' :
  4.                                 $addsql = ' AND heats>='.intval($heatslimit);
  5.                                 break;
  6.                         case 'digest' :
  7.                                 $addsql = ' AND digest>0';
  8.                                 break;
  9.                         default :
  10.                                 $addsql = '';
  11.                 }
  12.                 if(getglobal('setting/followforumid')) {
  13.                         $addsql .= ' AND '.DB::field('fid', getglobal('setting/followforumid'), '<>');
  14.                 }
  15.                 $tidsql = '';
  16.                 if($tids) {
  17.                         $tids = dintval($tids, true);
  18.                         $tidsql = DB::field('tid', $tids);
  19.                 } else {
  20.                         $limittid = intval($limittid);
  21.                         $tidsql = 'tid>'.$limittid;
  22.                         $fids = dintval($fids, true);
  23.                         if($fids) {
  24.                                 $tidsql .= is_array($fids) && $fids ? ' AND fid IN('.dimplode($fids).')' : ' AND fid='.$fids;
  25.                         }
  26.                         if($dateline) {
  27.                                 $addsql .= ' AND dateline > '.intval($dateline);
  28.                         }
  29.                         if($type == 'newthread') {
  30.                                 $orderby = 'tid';
  31.                         } elseif($type == 'reply') {
  32.                                 $orderby = 'lastpost';
  33.                                 $addsql .= ' AND replies > 0';
  34.                         } else {
  35.                                 $orderby = 'lastpost';
  36.                         }
  37.                         $addsql .= ' AND displayorder>=0 ORDER BY '.$orderby.' DESC '.DB::limit($start, $limit);
  38.                 }
  39.                 return DB::fetch_all("SELECT * FROM ".DB::table('forum_thread')." WHERE ".$tidsql.$addsql);
  40.         }
复制代码

查询语句就在这里出现了,可是……不懂……

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-12 18:56
本帖最后由 abababa 于 2024-8-12 20:04 编辑
kuing 发表于 2024-8-12 16:52
@hbghlyj 别光点赞,帮我分析一下呗

首页四格的 html 代码在 template\default\forum\discuz.htm 里,不过 ...


我下午看到主楼那个错误了,以为又坏了。下面是网友给的建议:
分别注释掉
  1. $grids['xxx']
复制代码
,或分别给予它们默认值,看看有什么结果。把报告出错的 sql 放进终端里单独运行,看有没有问题。如果确认是大表的问题,并且用 mysqli 的,就在运行前加一句 $mysqli->query("SET SQL_BIG_SELECTS=1");,临时允许大表查询。

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-12 19:06
abababa 发表于 2024-8-12 18:56
我下午看到主楼那个错误了,以为又坏了。下面是网友给的建议:
分别注释掉 $grids['xxx'],或分别给予它 ...


下午那会我是在做各种调试研究,你进来时应该恰好是开启首页四格的状态😄

主要是我完全不熟悉 mysql,也不敢乱运行……

先吃个饭,回来再鼓捣……

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-12 20:03
kuing 发表于 2024-8-12 19:06
下午那会我是在做各种调试研究,你进来时应该恰好是开启首页四格的状态😄

主要是我完全不熟悉 mysql,也 ...


“四格”应该就是这四个吧:
  1. $grids['digest'],$grids['image'],$grids['image'],$grids['newthread']
复制代码

然后网友的意思应该是分别注释掉,看看是哪格出了问题。
我觉得是不是能单独弄一个index2.php之类的呢?然后在那个页里试就行了。

哦,这个是哪里的问题,不加代码环境,有的就变成斜体了,是括号的问题?

点评

变斜体是 \$grids['digest'],\$ 识别成公式了啊🤭  发表于 2024-8-12 20:43
原来如此,是$的问题  发表于 2024-8-13 17:54

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-13 02:30
本帖最后由 kuing 于 2024-8-13 02:49 编辑
abababa 发表于 2024-8-12 20:03
“四格”应该就是这四个吧:
然后网友的意思应该是分别注释掉,看看是哪格出了问题。
我觉得是不是能单独 ...


首页四格有两种选择:
图文并茂:幻灯+新帖+新回复+热帖;
简洁文字:新帖+新回复+热帖+精华贴;

我后台选的是第一种,相对应的大概就是
$grids['image']$grids['newthread']$grids['newreply']$grids['hot']

1楼截图中 Debug 的第3点 Line 168 就是 $grids['hot'] 那行,也就是热帖那一格。

我尝试注释掉它,果然就不报错了,现在四格最后一格为空。

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-13 02:58
本帖最后由 kuing 于 2024-8-13 13:40 编辑
把报告出错的 sql 放进终端里单独运行,看有没有问题。
  1. SELECT * FROM pre_forum_thread WHERE tid>0 AND heats>=3 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 10
复制代码

PixPin_2024-08-13_02-50-58.png
还是同样的 #1104 提示。

另外,我还尝试了,将 heats>=3 改成 heats>=10(提高“热帖”的阀值),就能够查询成功!:
PixPin_2024-08-13_02-56-04.png

这个查询行数到底具体是指什么,怎么计算的?列也要算吗?

如果什么条件都不加,仅 SELECT * FROM pre_forum_thread 也能查询,整个主题列表就 9935 个条目,加了条件反而会变大吗?

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-13 17:31
kuing 发表于 2024-8-13 02:58
还是同样的 #1104 提示。

另外,我还尝试了,将 heats>=3 改成 heats>=10(提高“热帖”的阀值),就能 ...

我也不怎么懂这个,这个和那个顺序有关吗?就是tid>0 AND heats>=3 AND displayorder>=0这三个,应该是三个条件吧,要是和顺序有关的话,能不能先把最能减少结果的那个条件放在前面,比如heats>=3这个,要是它最能减少结果,放在前面会不会更好?这样能消除那个错误吗?

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-13 18:52
abababa 发表于 2024-8-13 17:31
我也不怎么懂这个,这个和那个顺序有关吗?就是tid>0 AND heats>=3 AND displayorder>=0这三个,应该是三 ...

刚才试过了,换了几个顺序,都不行

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-13 19:35
kuing 发表于 2024-8-13 18:52
刚才试过了,换了几个顺序,都不行

我也不懂这些,刚才问了网友,这是他刚才说的:
得看你查询的是表还是视图,如果是视图,可能有隐藏的 join 你不知道,如果是表,我也不知道什么原因,你想让它好用就按我之前说的 $mysqli->query("SET SQL_BIG_SELECTS=1");,然后再慢慢找原因。

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-13 20:49
abababa 发表于 2024-8-13 19:35
我也不懂这些,刚才问了网友,这是他刚才说的:
得看你查询的是表还是视图,如果是视图,可能有隐藏的 jo ...


这些概念我都不了解😥……

我又试了一下:
  1. SELECT * FROM pre_forum_thread WHERE heats>=3 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 10
复制代码

这个可以,而
  1. SELECT * FROM pre_forum_thread WHERE heats>=3 AND tid>0 ORDER BY lastpost DESC LIMIT 10
复制代码

这个就报错。

我查看这个表,按 displayorder 排列,发现只有 5 个 displayorder 的值是 -4(似乎都是被删的帖子,但我记得回收站已经清空,不知为何还有残留)。
而 tid>0 当然是全部(明显为多余条件),也就是说 displayorder>=0 会比 tid>0 少五个结果,这就导致一个行一个不行?恰好到了临界点吗?

等过一段时间,再多几个主题帖后,看前者还行不行……

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-13 21:16
kuing 发表于 2024-8-13 20:49
这些概念我都不了解😥……

我又试了一下:

如果是数量的原因,那么不加heats>=3这个条件,得到的数量应该更多吧(要求符合的条件越少结果越多)。那下面这个会不会有错误呢:
  1. SELECT * FROM pre_forum_thread WHERE tid>0 ORDER BY lastpost DESC LIMIT 10
复制代码

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-13 21:34
abababa 发表于 2024-8-13 21:16
如果是数量的原因,那么不加heats>=3这个条件,得到的数量应该更多吧(要求符合的条件越少结果越多)。那 ...

还有网友刚才的建议:
你用 EXPLAIN 加在原 SELECT 前,解释一下这个查询,这个执行之后只返回一行,你看那里的 rows 是多少,我猜这个 rows 已经超过你设置的 MAX_JOIN_SIZE 了,所以它会报错。但我不能解释这个现象,因为你说你的表行远小于 MAX_JOIN_SIZE。也可能是某些版本的 bug,你可以去专业的 mysql/mariadb 官方社区再问问。

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-13 22:38
abababa 发表于 2024-8-13 21:16
如果是数量的原因,那么不加heats>=3这个条件,得到的数量应该更多吧(要求符合的条件越少结果越多)。那 ...

这个不报错,下面这个也不报错
  1. SELECT * FROM pre_forum_thread WHERE tid>0 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 10
复制代码

所以我完全理解不了。

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-13 22:59
本帖最后由 kuing 于 2024-8-13 23:20 编辑
abababa 发表于 2024-8-13 21:34
还有网友刚才的建议:
你用 EXPLAIN 加在原 SELECT 前,解释一下这个查询,这个执行之后只返回一行,你看 ...

  1. EXPLAIN SELECT * FROM pre_forum_thread WHERE tid>0 AND heats>=3 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 10
复制代码

这样吗?结果是
PixPin_2024-08-13_22-58-36.png
才 4961 个 rows ……

如果去掉 tid>0 和 displayorder>=0,即
  1. EXPLAIN SELECT * FROM pre_forum_thread WHERE heats>=3 ORDER BY lastpost DESC LIMIT 10
复制代码

那 rows 变成 6699

如果连后面的排序都去掉,即
  1. EXPLAIN SELECT * FROM pre_forum_thread WHERE heats>=3
复制代码

rows 变成 9922

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-14 09:06
kuing 发表于 2024-8-13 22:38
这个不报错,下面这个也不报错

所以我完全理解不了。


搜到一个类似的帖子:
forum.joomla.org/viewtopic.php?t=995872

好像是和网友说的那个SET SQL_BIG_SELECTS=1有关。

我看现在已经好了,那个热帖的格出来了。

730

主题

1万

回帖

9万

积分

积分
93623
QQ

显示全部楼层

 楼主| kuing 发表于 2024-8-14 13:35
本帖最后由 kuing 于 2024-8-14 13:59 编辑
abababa 发表于 2024-8-14 09:06
我看现在已经好了,那个热帖的格出来了。


那是我改了代码才出来的😁
就是根据 public function fetch_all_for_guide... 那段最后 return 的格式,将
  1. $grids['hot'] = C::t('forum_thread')->fetch_all_for_guide('hot', 0, array(), 3, 0, 0, 10, $_G['setting']['grid']['fids']);
复制代码

改成了
  1. $grids['hot'] = DB::fetch_all("SELECT * FROM ".DB::table('forum_thread')." WHERE heats>=10 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 10");//test
复制代码

就是不走那个函数,直接写查询语句,去掉了多余的 tid>0 条件。
也顺便将 heats>=3 改成 heats>=10,3 太小,很容易成为热帖,结果整格与“最新回复”差不了多少,10 合理一些。

至于 SET SQL_BIG_SELECTS=1 啥的暂时就不用了,先这样吧,再出现问题再说……

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2024-8-14 15:01
kuing 发表于 2024-8-14 13:35
那是我改了代码才出来的😁
就是根据 public function fetch_all_for_guide... 那段最后 return 的格式, ...

原来是改了东西才出来的。不过我看链接里说的,可能即使只把这一个数据集复制到别的电脑里,也不一定能重现那个错误。那把这个集合复制到自己的电脑里,也能出现同样的错误吗?
另外网友还提到一个“用 ANALYZE TABLE 刷新表统计信息”的,难道是虽然只有这几行,但统计出错了,统计成更多行了?网友说他也确定不了

手机版|悠闲数学娱乐论坛(第3版)

GMT+8, 2025-3-4 16:07

Powered by Discuz!

× 快速回复 返回顶部 返回列表