常见 GitLab 数据类型的清理
后知后觉 现有 1 评论

在部署 Geo 架构后,会遇到很多数据无法进行同步的问题,大部分是因为项目本身存在问题或者已经不存在,但数据库中存在残留记录。

常见类型数据的清理

在迁移或者升级 GitLab 时,会有很多孤儿数据或废弃数据需要进行清理。

清理 Abuse reports

使用 rails console 执行命令进行清理:

# 直接使用网页链接中的数字 ID 进行查询删除即可
report = AbuseReport.find(1)
report.destroy

清理 Snippet repository

查看同步的报错,在主节点数据库执行 SQL 查询:

select snippet_id, snippet_project_id, verification_failure, snippet_project_id, snippet_organization_id from snippet_repositories;

Snippet 仓库分为两种:

前者绑定项目,后者绑定个人。查询和清理的方法略有不同,使用 rails console 执行命令进行清理:

# 获取某个项目 Snippet(假设 ID 为 123)
snippet = ProjectSnippet.find(123)

# 获取对应的 Repository 对象
repo = snippet.repository

# 查看仓库的路径和相关信息
repo.full_path               # 仓库的完整路径
repo.disk_path               # 存储在磁盘上的相对路径
repo.project                 # 所属的项目
repo.repository_storage      # 存储位置(如 default)
repo.repository_storage_path # 实际路径

# 获取某个用户 Snippet(假设 ID 为 456)
snippet = PersonalSnippet.find(456)

# 获取对应的 Repository 对象
repo = snippet.repository

# 查看仓库的路径和相关信息
repo.full_path
repo.disk_path
repo.repository_storage
repo.repository_storage_path

查询所有的 snippet 仓库 ID 或 Path,可以执行:

ProjectSnippet.all.each do |s|
  puts "#{s.id} => #{s.repository.disk_path}"
end

PersonalSnippet.all.each do |s|
  puts "#{s.id} => #{s.repository.disk_path}"
end

对于仓库 snippet 存储路径,可以使用命令反查:

Gitlab::GitalyClient::StorageSettings['default']['path']

搭建 Geo 后,如果遇到报错 Error during verification: Repository does not exist 的 PersonalSnippet:

# 找出无效的 PersonalSnippet
invalid_snippets = PersonalSnippet.all.select do |s|
  begin
    !s.repository.exists?
  rescue => e
    puts "Error checking snippet #{s.id}: #{e.message}"
    true
  end
end
# 确认这些是否已经丢失
invalid_snippets.each { |s| puts "Missing repo for PersonalSnippet ##{s.id}" }
# Dry run 检查删除项
invalid_snippets.each do |s|
  puts "Would delete PersonalSnippet ##{s.id} (#{s.title})"
end
# 删除无效 PersonalSnippet
invalid_snippets.each do |s|
  puts "Deleting PersonalSnippet ##{s.id}"
  s.destroy!
end
补充:以上逻辑也同样适用于 ProjectSnippet,只需将 PersonalSnippet 替换为 ProjectSnippet 关键字。

如果实例中存在大量代码片段,可以分批执行,防止内存不足:

invalid_snippets = []
PersonalSnippet.find_each(batch_size: 100) do |s|
  invalid_snippets << s unless s.repository.exists? rescue true
end

其他可用类型及销毁

所有 geo 中涉及的对象类型,可以在官方手册中找到

通用的删除逻辑是

对象类型.find(id).destroy

建议实际删除前只查询,确认后再删除。


附录

参考链接

如果遇到问题或者对文章内容存疑,请在下方留言,博主看到后将及时回复,谢谢!
回复 / 查看「历史评论
回答20+26=
  1. avatarImg LiuChhs

    有没有其他类型的清理方式?比如用户或者空仓库

    Firefox 141.0 Android 15 回复
    IP 属地 未知