gitlab容器:could not read block 0 in file “base/16385/2702“

gitlab容器:could not read block 0 in file "base/16385/2702"

  • 一:报错场景说明
  • 二:解决步骤
  • 三:后续问题

一:报错场景说明

使用docker在局域网搭建gitlab服务,一直运行正常。有天突然断电,gitlab容器再启动时一直显示unhealthy状态,查看日志报如下错,结果是gitlab网页无法访问,所有仓库资源连接都变成502。

failed: ERROR:  could not read block 0 in file "base/16385/2702"
# 出现此信息则表示数据表文件损坏。这通常是由于异常断电或误操作导致的。这里“16385”是发生问题的数据库的对象id(oid), “2702”表示发生问题的表的文件结点(filenode)
# 如果发生损坏的表以及损坏的页面数量较少,我们可以以牺牲部分数据的代价恢复整体;如果损坏的表数量过多,或者损失的数据非常重要,就需要从备份中恢复数据了。

想着当务之急先备份数据,备份数据时还是报错:

root@monitor:/data/gitlab_docker# docker exec gitlab gitlab-rake gitlab:backup:create
Dumping database ... 
Dumping PostgreSQL database gitlabhq_production ... pg_dump: [archiver (db)] query failed: ERROR:  could not read block 0 in file "base/16385/2702": Input/output error
pg_dump: [archiver (db)] query was: SELECT tgname, tgfoid::pg_catalog.regproc AS tgfname, pg_catalog.pg_get_triggerdef(oid, false) AS tgdef, tgenabled, tableoid, oid FROM pg_catalog.pg_trigger t WHERE tgrelid = '19086'::pg_catalog.oid AND NOT tgisinternal
Backup failed
[FAILED]

百度谷歌找了一堆,最终找到这篇文章得以解决:

https://blog.csdn.net/international24/article/details/89710703

二:解决步骤

下面记录下本次解决的步骤:

1:进入gitlab容器

root@monitor:~/docker# ./docker_in.sh gitlab

2:查看gitlab配置文件

root@99c0ff133dc7:/# cat /var/opt/gitlab/gitlab-rails/etc/database.yml
# This file is managed by gitlab-ctl. Manual changes will be
# erased! To change the contents below, edit /etc/gitlab/gitlab.rb
# and run `sudo gitlab-ctl reconfigure`.

production:
  adapter: postgresql
  encoding: unicode
  collation:
  database: gitlabhq_production			# 数据库名
  pool: 10
  username: "gitlab"					# 用户名
  password:
  host: "/var/opt/gitlab/postgresql"	# 主机
  port: 5432
  socket:
  sslmode:
  sslrootcert:
  sslca:
  load_balancing: {"hosts":[]}
  prepared_statements: false
  statements_limit: 1000
  fdw:

3:查看/etc/passwd文件对应的gitlab用户

root@99c0ff133dc7:/# cat /etc/passwd
.........
gitlab-psql:x:996:996::/var/opt/gitlab/postgresql:/bin/sh		# postgresql数据库用户
mattermost:x:994:994::/var/opt/gitlab/mattermost:/bin/sh
registry:x:993:993::/var/opt/gitlab/registry:/bin/sh
gitlab-prometheus:x:992:992::/var/opt/gitlab/prometheus:/bin/sh
gitlab-consul:x:991:991::/var/opt/gitlab/consul:/bin/sh

4:切换到gitlab-psql用户登录数据库

root@99c0ff133dc7:/# su - gitlab-psql
$

登录数据库,由于gitlab容器中只有一个数据库,名为gitlabhq_production,所以无须排查是哪个库报错

$ psql -h /var/opt/gitlab/postgresql -d gitlabhq_production
psql (9.6.8)
Type "help" for help.

gitlabhq_production=#

5:修复数据
查找损坏的数据库对象。连接发生问题的数据库,执行下面的sql语句:

gitlabhq_production=# select relname,relkind from pg_class where relfilenode=2702;                                                                                     relname        | relkind
----------------------+---------
 pg_trigger_oid_index | i
(1 row)

如果查询结果中 relkind = r,表示损坏的是表,例如:

tb_door, r
relname = tb_door	# 这表示损坏的表是tb_door。

如果查询结果中relkind = i,表示损坏的是一个索引。例如:

dept_number_index, i

或者:

tb_dept_pkey, i

需要注意,损坏的可能是普通索引,也可能是主键或唯一键。如果索引的名称中有“_pkey”等很可能属于主键,而名称中含有 “_key”则很可能属于唯一键。

还需要格外注意一点,表/索引可修复的前提条件是损坏的表是应用程序创建的表/索引,而不是PostgreSQL的系统表和建立在其上的索引。如果系统表/建立在其上的索引发生损坏,则需要从备份中恢复数据库。判断一个表是否是系统表,最简单的方法是:如果表名是“pg_”开头的,则说明它是系统表。

小知识
pgclass.relkind 的值有下面几种:
r: 表示ordinary table(普通表);
i: 表示index(索引);
S: 表示sequence(序列);
V: 表示view(视图);
m: 表示materialized view(物化视图);
c: 表示composite type(复合类型);
t: 表示TOAST table(TOAST 表);
f: 表示foreign table(外部表)

下面为修复命令:

gitlabhq_production=# set zero_damaged_pages = on;
SET
gitlabhq_production=# reindex index pg_trigger_oid_index;
REINDEX

修复完成后,gitlab所有页面都可以正常访问了。

三:后续问题

上面是修复索引后,页面是可以正常访问了,但在备份数据时报错:

root@monitor:/data/gitlab_docker# docker exec gitlab gitlab-rake gitlab:backup:create
Dumping database ... 
Dumping PostgreSQL database gitlabhq_production ... pg_dump: [archiver (db)] query failed: ERROR:  could not read block 0 in file "base/16385/19407": read only 4096 of 8192 bytes
pg_dump: [archiver (db)] query was: SELECT sequence_name, start_value, increment_by, CASE WHEN increment_by > 0 AND max_value = 9223372036854775807 THEN NULL      WHEN increment_by < 0 AND max_value = -1 THEN NULL      ELSE max_value END AS max_value, CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL      WHEN increment_by < 0 AND min_value = -9223372036854775807 THEN NULL      ELSE min_value END AS min_value, cache_value, is_cycled FROM public.clusters_applications_helm_id_seq
Backup failed
[FAILED]

通过SQL语句查看,上面的1904是一个序列:

gitlabhq_production=# select relname,relkind from pg_class where relfilenode=19407;
              relname              | relkind
-----------------------------------+---------
 clusters_applications_helm_id_seq | S
(1 row)

这个序列如何修复?未知,记着先。结果就是gitlab无法备份数据。

你可能感兴趣的:(Linux运维,gitlab)