今天我尝试将我的 Discourse 安装从 2.9.0.beta9 升级到 2.9.0.beta10。但这次升级出了大问题。
我的第一次尝试是在控制台上
cd /var/discourse
sudo git pull
sudo ./launcher rebuild app
最后以这个消息中断,日志中间有这样的信息:
PG::InvalidParameterValue: ERROR: cannot extract elements from a scalar
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:110:in `exec'
我通过启动旧的镜像(它仍然存在)成功地恢复了论坛。
我的第二次尝试是通过 Web 控制台(/admin/upgrade)。但最后也因为同样的错误而中断:ERROR: cannot extract elements from a scalar。当我回到升级面板时,它告诉我所有组件都已成功更新。但在容器重启后,服务器现在抛出了一个 HTTP 500 错误
我在一台单独的机器上进行了干净安装,从头开始。我能够安装 beta10 版本,但尝试从备份恢复时出现了完全相同的错误!
有谁能提供帮助吗?
我找到了导致它卡住的查询
INSERT INTO question_answer_votes (post_id, user_id, created_at)
SELECT
X.post_id AS post_id,
(X.value->>'user_id')::int AS user_id,
(X.value->>'created_at')::timestamp AS created_at
FROM (
SELECT
post_id,
jsonb_array_elements(value::jsonb) AS value
FROM post_custom_fields WHERE name = 'vote_history'
) AS X
WHERE (X.value->>'action') != 'destroy'
ORDER BY (X.value->>'created_at')::timestamp DESC
ON CONFLICT DO NOTHING
如果我的理解没错的话,这是因为 psql 函数 jsonb_array_elements 期望接收一个数组,但却收到了一个 NULL 值。
已经有几份关于此的报告:
I am trying to rebuild one (forum.techandtiny.com ) of three Discourse instances that I run on my server. The crazy part is the plugins used are identical to the two other instances (forum.tabletpc.review and forum.farfarawaynews.com ) that I run on my server. However, in updating all three instances today, only this one fails to spin up after rebuilding. Attached is the terminal output.
Unable to install Discourse Question Answer
== 20211020062413 CreateQuestionAnswerVotes: migrating ========================
-- create_table(:question_answer_votes, {})
-> 0.0478s
-- add_index(:question_answer_votes, [:post_id, :user_id], {:unique=>true})
-> 0.0024s
-- execute("INSERT INTO question_answer_votes (post_id, user_id, created_at)\nSELECT\n X.post_id AS post_id,\n (X.value->>'user_id')::int AS user_id,\n (X.value->>'created_at')::timestamp AS created_at\nFROM (\n SELECT\n …
我认为这可能与之前安装了 Pavilion Question/Answer 插件有关?
我会找人深入研究一下。
我们正在使用这个插件:https://github.com/angusmcleod/discourse-question-answer。
它似乎与 Pavilion Question and Answer 插件有关。
它是 discourse/discourse-upvotes 插件的一个分支。
1 个赞
为了确认一下,您的 app.yml 中有哪些插件?
1 个赞
pfaffman
(Jay Pfaffman)
2022 年10 月 6 日 10:44
9
我看到的网站上有很多自定义帖子字段,其中包含许多经过多次编码的字符串,导致它们无法使用。
一些解决方案,按复杂程度排序:
停止使用该插件(并可能切换到新的“赞成票”)
删除所有这些字段
删除不好的字段
编辑这些字段,将数据恢复为有效的 JSON 字符串。
我看到的网站上有几年前的错误数据。这似乎是一个多年前存在的错误,现在才被发现。
可能可以编写代码来修复损坏的 JSON 字符串,但我花了 10 分钟也未能弄清楚如何做到这一点。
请参阅 Question Answer Plugin - #301 by pfaffman 获取示例。
2 个赞
nat
(Natalie T)
2022 年10 月 6 日 10:57
10
Jay Pfaffman:
停止使用该插件(也许可以切换到新的点赞功能)
我也这么想过,但快速查看了 Angus 的分支,似乎没有进行任何数据迁移。 https://github.com/angusmcleod/discourse-question-answer/compare/main...discourse:discourse-upvotes:main
正如你所说,这感觉像是旧的问答帖造成的数据污染。我也觉得奇怪的是,这现在才出现,考虑到这次迁移是 2021 年 11 月的——我猜是因为 JayJay 现在才切换到新插件?无论如何,我们会再次查看这次迁移。
1 个赞
- git clone https://github.com/discourse/docker_manager.git
- git clone https://github.com/discourse/discourse-solved.git
- git clone https://github.com/unfoldingWord-dev/discourse-mermaid.git
- git clone https://github.com/angusmcleod/discourse-question-answer.git
- git clone https://github.com/discourse/discourse-checklist.git
- git clone https://github.com/discourse/discourse-cakeday.git
- git clone https://github.com/discourse/discourse-canned-replies.git
- git clone https://github.com/discourse/discourse-footnote.git
- git clone https://github.com/discourse/discourse-staff-notes.git
- git clone https://github.com/discourse/discourse-graphviz.git
- git clone https://github.com/discourse/discourse-assign.git
- git clone https://github.com/discourse/discourse-voting.git
- git clone https://github.com/discourse/discourse-yearly-review.git
- git clone https://github.com/discourse/discourse-saved-searches.git
1 个赞
@nat 我根本不会切换到新插件。我仍然在使用我们已经使用了一段时间的插件集。
至少每个月,我们都会运行更新,所以版本之间不会有很大的差距。
2 个赞
除了问答问题之外,还有一个小小的“供您参考”的说明,现在还有一个可以替代预设回复的功能:
Summary
Discourse Templates allows the creation of content templates for repeated use. The templates are stored as topics in a special category, where they can be edited and discussed as needed.
Install Guide
This plugin is bundled with Discourse core. There is no need to install the plugin separately.
This plugin is pretty much a new version of Discourse Canned Replies but it is more flexible and stores the templates in a differ…
而且我相信现在还有一个官方的 Mermaid 主题组件:
1 个赞
如果我移除该插件,恢复备份仍然会导致有问题的查询运行。
因此,我需要移除该插件以及该插件使用的任何表+查询。
我将如何知道涉及的表?
Stephen
(Stephen)
2022 年10 月 6 日 11:49
18
您是否已注释掉该插件的行并尝试重新构建以进行确认?
2 个赞
我马上就试试。我查看了备份中的 dump.sql 文件,里面根本没有提到任何 question_answer_* 表。这让我很乐观……
1 个赞
pfaffman
(Jay Pfaffman)
2022 年10 月 6 日 12:13
21
损坏的数据位于 PostCustmField 表中。但是,如果您没有该插件,它将不会尝试将这些数据迁移到新表中。
Natalie T:
无论如何,我们会再次查看这次迁移。
问题不在于迁移本身,而在于过去某个时候数据被损坏了。它已经损坏了,但损坏的方式多年来一直未被发现。我认为也许每一次新的点赞都会使其进一步损坏。一个合理的修复方法可能是忽略损坏的数据,也许将其标记为损坏(也许重命名自定义字段),以便将来的迁移可以忽略它,并且有人可以根据需要手动修复它们。
2 个赞
在生产环境中也成功了。禁用了插件,然后我们继续进行。
仍然想知道为什么我没有更早遇到这个问题。正如我所说,我们每个月都会例行更新所有系统,所以我应该更早地看到这个问题。
我如何能够自己连接到 Discourse 数据库,以验证 post_custom_fields 表中的内容?
angus
(Angus McLeod)
2022 年10 月 6 日 13:14
23
@Jaap-Jan_Swijnenburg 很抱歉您遇到了问题。
Jay Pfaffman:
迁移本身不是问题
我对此持不同意见
旧的 QnA 插件使用了 标准的 Discourse 自定义字段类型转换 ,该转换旨在将该字段转换为 JSON。但在某些情况下(例如此情况)不起作用,这就是为什么您(理想情况下)在处理 Discourse 自定义字段时需要进行格式检查(尤其是在处理像这样相当旧的代码和数据时)。我建议 Upvotes 插件在此处需要执行此操作,这确实是当前错误来源的地方。
您可以使用数据浏览器插件来检查您在那里有什么。
Summary
Discourse Data Explorer allows you to make SQL queries against your live database, allowing for up-to-the-minute stats reporting.
Install Guide
This plugin is bundled with Discourse core. There is no need to install the plugin separately.
If you’re looking for examples or support for any custom queries, you can find lots of topics in our Data & reporting category under the sql-query tag. If there’s not one to suit your pa…
pfaffman
(Jay Pfaffman)
2022 年10 月 6 日 20:35
24
Angus McLeod:
我将尊重地与您在此处意见不合
好吧,我在这方面大多听从您的意见,而且我认为我们确实意见一致。我认为迁移在数据没有损坏的情况下是有效的,这一点是正确的。我们同意,如果数据损坏,它应该比现在更优雅地失败。
是的,但数据可能在几年前就已损坏(我熟悉的网站就是这种情况),但您没有注意到,因为它没有发生灾难性故障。我很确定它没有像预期的那样管理投票,但没有人注意到。
我会从 rails 进行,类似这样:
./launcher enter app
rails c
然后是这样的东西:
all_votes=PostCustomField.where(name: "vote_history")
likely_broken_votes=PostCustomField.where(name: "vote_history").where("value like '\\\"%'")
只查看 id 和数据:
all_votes.pluck(:id,:value)
获取一个 pcf:
pcf=PostCustomField.find(1234)
修复它
pcf.value='您真正想要的东西'
pcf.save
angus
(Angus McLeod)
2022 年10 月 7 日 09:38
28
这里发生的情况是这样的:
有些人在他们的 app.yml 文件中有一个非常旧版本的问答插件,其存储库 URL 中包含我的个人 GitHub 用户名。
我多年前已将 QnA 插件转移到 paviliondev。GitHub 会在存储库转移时重定向 URL,因此包含我个人用户名的旧 URL 仍然有效。
多年后,Pavilion 将 Question Answer 插件转移到了 Discourse。Discourse 最初保留了名称 discourse-question-answer。
几个月前,我创建了我自己的插件分支,托管在 discourse 中,当时它仍然被称为 discourse-question-answer。
那些拥有指向包含我的个人 GitHub 帐户的 QnA 插件的非常旧链接的人,现在正在克隆托管在 discourse 中、经过显著更新的 discourse-question-answer 的新分支。换句话说,一个非常旧的链接现在指向了一个新插件的分支。尽管已经过去了这么多年,我本应该预料到这一点,对此我感到抱歉。我已经删除了那个分支。
Discourse 将 discourse-question-answer 的名称更改为 discourse-upvotes。这个名称更改对您的情况 @Jaap-Jan_Swijnenburg 没有实质性影响,但这就是为什么您现在(意外地)克隆该存储库分支的原因。
discourse/discourse-upvotes(以前是 discourse-question-answer)中的迁移假定 post_custom_fields 中的 value 列是 JSON 类型安全的。
该插件在 angusmcleod/discourse-question-answer(多年前)时创建的旧数据,并未被 discourse/discourse 中的 HasCustomFields 关联保存为有效的 JSON。我猜测,这些数据可能是在添加 JSON 类型检查 4 年前 之前添加的(在边缘情况下,注册为 JSON 的自定义字段中仍然可能出现无效 JSON)。
因此
当那些在 app.yml 中拥有(过时多年的)angusmcleod/discourse-question-answer URL 的人在更新他们的 Discourse 时,会克隆插件的新版本中的迁移,迁移运行,并可能产生此错误。
有几种解决方案:
@Jaap-Jan_Swijnen元 ,在您的情况下,您只需要删除指向我旧 QnA 插件的引用,就可以重建您的站点。就是这样;仅此而已。看起来您已经做到了
可以更新 discourse/discourse-upvotes 插件的迁移,以处理 post_custom_fields 中 value 列中的非 JSON 值。
我想指出的是,2 也可以处理那些确实想从旧版 QnA 插件切换到 discourse-upvotes 的用户的情况。在这种情况下,迁移将运行,如果 post_custom_fields 的 value 列中的任何条目不是有效的 JSON,迁移将失败。
5 个赞