使用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无法备份数据。