多站点将上传内容恢复为“默认”而非实际数据库名称

在 Discourse 最新测试版(Docker 安装,多站点模式)上遇到问题。

尝试将原始数据库 REDACTED 的备份恢复到当前数据库 db8015。上传的文件最终都进入了 default,无论是在文件系统中还是在数据库中。

无论是通过 GUI 触发恢复,还是使用 RAILS_DB=db8015 RAILS_ENV=production script/discourse restore 在命令行执行恢复,都会出现此问题。

在恢复过程中,RailsMultisite::ConnectionManagement.current_db 从正确的数据库切换到了 default。我已将问题定位到 db.rake 中的 [Rake::Task['db:_dump'].invoke

在该行之前,RailsMultisite::ConnectionManagement.current_db 的值是正确的(db8015),但在该行之后,它变成了 default

看起来 这个修复 以某种方式破坏了生产环境,@sam

日志:

[STARTED]
'DHSupport' 已启动恢复!
将恢复状态标记为运行中...
确保 /var/www/discourse/tmp/restores/db8015/2019-10-11-104940 存在...
将归档文件复制到临时目录...
解压归档文件,这可能需要一些时间...
没有要提取的元数据文件。
验证元数据...
  当前版本:20191007140446
  恢复版本:20190908234054
提取转储文件...
在 discourse_functions 架构中创建缺失的函数
无法恢复到不同的架构,正在原地恢复
启用只读模式...
暂停 sidekiq...

[删除了大量不相关的内容]

清除主题缓存
提取上传文件...
重新映射上传文件...
将 'uploads/REDACTED' 重新映射为 'uploads/default'
优化站点图标...
帖子将由 sidekiq 中的后台作业重新渲染。在该过程完成之前,您将看到缺失的图片。
您可以通过手动运行 "rake posts:rebake_uncooked_posts" 来加速此过程。
执行 after_restore_hook...
清理内容...
从 discourse_functions 架构中删除函数
删除临时目录 '/var/www/discourse/tmp/restores/db8015/2019-10-11-104940'...
恢复 sidekiq...
将恢复状态标记为完成...

这个问题还存在吗 @sam

澄清一下,复现步骤如下:

  • 在 Docker 容器中创建一个多站点

  • 备份其中一个多站点

  • 在新的 Docker 容器中恢复该备份

  • 上传文件的位置不正确

@kris.kotlarek 你能在本地复现此问题并尝试修复吗?

我怀疑我们未来会再次遇到这个问题。

只需目标容器为多站点即可复现此问题。

  • 在 Docker 容器中创建一个论坛
  • 创建备份
  • 在新的多站点 Docker 容器中恢复该备份
  • 上传文件的位置不正确

我花了一些时间研究这个 bug,想向您汇报我的发现。基本上,我确认了您之前所说的所有内容,恢复流程如下:

migrate_database
reconnect_database
...
extract_uploads

问题在于,迁移任务完成后,reconnect_database 并没有切换到目标数据库,而是开始操作默认数据库。

因此,这段代码是错误的:

def extract_uploads
  ...
  current_db_name = 
  RailsMultisite::ConnectionManagement.current_db # default
  optimized_images_exist = File.exist?(File.join(tmp_uploads_path, 'optimized'))

一个权宜之计是在此处使用 @current_db,它仍然包含正确的数据库名称,而不是 RailsMultisite::ConnectionManagement.current_db,但这并没有解决 reconnect_database 为何无法正常工作这一根本问题。

我需要深入排查以找到问题所在。

你确定这确实是在迁移任务之后发生的吗?

这段代码

  migrate_database
  puts "迁移后,重新连接前 #{RailsMultisite::ConnectionManagement.current_db}"
  reconnect_database

输出如下:

正在优化站点图标... 完成
迁移后,重新连接前 default
正在重新连接到数据库...

但当你注释掉 lib/tasks/db.rake 中的这一行:

Rake::Task['db:_dump'].invoke

输出变为:

正在优化站点图标... 完成
迁移后,重新连接前 db8015
正在重新连接到数据库...

你说得对。我从 restorer.rb 中移除了 Rake::Task["db:migrate"].invoke,整个过程中数据库都正常了。你比我领先一步,我现在的计划是进入迁移任务,看看是哪一步导致了问题。感谢你指出 _dump,我会直接去那里查看内部发生了什么。

我花了一些时间调查这个问题,但最终还是找到了解决方法 :slight_smile:

谢谢!

经过进一步思考,在非主数据库上运行 db:dump 究竟意味着什么?

如果数据库不是默认的,它不就应该直接跳过 db:dump 命令吗?

修复已合并,感谢您发现该问题。添加该 dump 命令是因为多站点迁移存在问题。我认为使用哪个数据库来导出结构并不重要,因为所有多站点应具有相同的结构。