禅道 20.3.0 开源版,备份时报错,导致备份SQL失败。

回贴
回帖数 5
阅读数 450
发表时间 2024-07-23 01:49:16
🚆
1 楼主

---

执行备份时,系统报错


Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'zentao.metriclib_distinct' doesn't exist ,the sql is: 'select * from `metriclib_distinct`' in /apps/zentao/lib/dbh/dbh.class.php:107 

Stack trace:

 #0 /apps/zentao/lib/dbh/dbh.class.php(153): dbh->sqlError(Object(PDOException))

 #1 /apps/zentao/lib/zdb/zdb.class.php(255): dbh->query('select * from `...')

 #2 /apps/zentao/module/backup/model.php(25): zdb->dump('/apps/zentao/tm...')

 #3 /apps/zentao/module/backup/zen.php(64): backupModel->backSQL('/apps/zentao/tm...')

 #4 /apps/zentao/module/backup/control.php(197): backupZen->backupSQL('202407230139135...', 'yes') 

#5 /apps/zentao/framework/base/router.class.php(2480): backup->backup('yes', 'manual') 

#6 /apps/zentao/framework/router.class.php(770): baseRouter->loadModule() 

#7 /apps/zentao/www/index.php(88): router->loadModule() 

#8 {main} thrown in /apps/zentao/lib/dbh/dbh.class.php on line 107


---------------

使用 docker版本 20.3.0 

MYSQL 8.0


-----------

全文搜索 

metriclib_distinct 关键词,定位到:

\zentaopms\module\metric\tao.php 有这个临时表的建立函数。


但是在备份动作时,不知道什么原因,触发了对这个临时表的备份。(肯定是找不到的拉~)


2024-07-23 10:54:08 1 最后编辑
5个回复
孔令茂 沙发

 备份的逻辑分为两步,首先获取所有的表名,其次循环查询表的数据生成备份语句。

根据您的反馈,可能的原因是

1. 其他同事触发了临时表的建立函数 createDistinctTempTable,执行数据生成需要一定的时间

2. 备份的按钮触发,获取所有数据表时 metriclib_distinct 是在集合中的。

3. createDistinctTempTable ,执行删除表的操作

4. 备份的逻辑开始查询 metriclib_distinct  表的数据 (此时表已不存在,系统保存致命错误)

这块禅道的备份逻辑需要增强,在查询数据库表的数据时应判断表是否存在。


您再次点击备份应该可以成功。

或者执行完语句  DROP TABLE IF EXISTS `metriclib_distinct` ,后再备份。

2024-07-23 11:19:14 孔令茂 回帖
🚆
1 板凳
你的分析逻辑是对的

我单机 一人 DOCKER部署 依然出现这个问题。

且 docker启动后 无人使用的情况下 这个报错的触发也非常频繁。


目前造成的问题在于  备份不稳定。


(可查看2次故障的间隔周期)

2024-07-23 18:07:25 1 回帖
孔令茂 #3

这块我们内部反馈一下。


你可以使用一个临时方案

1. 找到 lib/zdb/zdb.class.php

2. 第238行下面增加几行代码,用来再次判断表是否存在

```

/* Check table exists. */
$showTable = $this->dbh->query("show tables like `$table`")->fetch();
if(empty($showTable)) continue;

```


2024-07-23 18:32:27 孔令茂 回帖
🚆
1 #4 回复#3
原帖由 孔令茂 于 3个回复 发表

这块我们内部反馈一下。


你可以使用一个临时方案

1. 找到 lib/zdb/zdb.class.php

2. 第238行下面增加几行代码,用来再次判断表是否存在

```

/* Check table exists. */
$showTable = $this->dbh->query("show tables like `$table`")->fetch();
if(empty($showTable)) continue;

```



这个方法有效,是一个有效的补丁。

不过 在 MYSQL 8上 


 `$table` 需要改为  '$table'

 否则会报错。



此外 由于目前禅道没有涉及事务处理,所以 show tables 在并发备份或者类似场景时,依然会 出现 判断错误的问题。

我临时的解决方案是:

$showTable = $this->dbh->query("SELECT  * FROM  `$table` LIMIT 1")->fetch();
虽然性能上差很多,但是可以接受反复触发(其实就是那延迟形成了一个隐形的锁)


本质上,这个问题要高效解决,建议是如下的思路去处理:

1、考虑使用 临时表而不是真实的表,例如:CREATE TEMPORARY TABLE  

2、在这个基础上,使用事务处理,避免出现幻读问题。

2024-07-23 21:28:31 1 回帖
禅道-丁卓 #5 回复#4

恭喜解决了问题。

我们这边和开发团队沟通下解决方案 (反馈id6508),有最新的消息,在此回复。

2024-07-24 11:13:35 孔令茂 最后编辑 2024-07-24 11:13:35 禅道-丁卓 回帖
联系人
刘斌/高级客户经理
电话(微信)
17685869372
QQ号码
526288068
联系邮箱
liubin@chandao.com
返回顶部
刘斌
高级客户经理
17685869372
526288068
统一服务热线 4006-8899-23
我要提问提问有任何问题,您都可以在这里提问。 问题反馈反馈点击这里,让我们聆听您的建议与反馈。