Self-Hosted Sentry外置数据库及数据库及迁移记录

156 阅读3分钟

背景(Situation)

Sentry 是一款开源的前端监控组件,被广泛应用于各类 Web 应用、移动应用以及后端服务中,用于实时捕获和报告应用程序中的错误、性能问题。

Sentry开发团队后续更是推出了 Self-Hosted Sentry,一种基于docker和docker-compose部署的可开箱即用,适用于小规模入门应用的sentry。


我司的Self-Hosted Sentry服务移交到我手上后,先后踩了 版本升级磁盘耗尽 的坑。

版本升级,可以参考此文章: develop.sentry.dev/self-hosted…

磁盘耗尽,由于sentry服务依赖postgres(后称pg),而pg存在逻辑删除及死元组问题,导致其真实数据大小和磁盘占用空间相去甚远。pg超过1T,实际约100G+。

而且此时执行vacuum fullvacuumdb -U postgres -d postgres -v -f --analyze,已然不可能。

image.png

目标(Target)

如果数据库交由DBA管控,专业的人做专业的事(甩锅),并且他们可以周期对数据库进行备份。大大降低数据遗失风险。

团队商定使用外接pg方案,其实如果从零搭建sentry,这本身没啥难度,但是如果考虑到数据迁移,问题就变很多了。拆解完,主要是两个问题:

  1. 数据库如何初始化
  2. 老库数据导出和新库导入

行动(Action)

数据库如何初始化

根据sentry镜像版本,安装pg,我的版本作为参考。

self-hosted sentry: 25.1.0

pg: 16

安装sentry必要的pg插件:

NameVersionSchema
citext1.6public
plpgsql1.0pg_catalog

老库数据导出和新库导入

这个才是最坑的点,没搞过兄弟们,肯定觉得pg_dump就完了,但是由于表太大,会报错,如下图所示。

image.png

考虑分布导出

其中最大的表是:nodestore_node,实测超过900GB。psql+分时间段导出。

但是,兄弟们还有一个坑,把其他容器都停掉,再导出。

方案如下:

第一步:备份源数据库(远程)

# 备份全局对象(角色、权限等)
pg_dumpall --globals-only -h 10.1.1.1 -p 15432 -U postgres > /root/backup_mydb_global.sql

# 备份除 nodestore_node 外的全部数据,
# !!!注意一定要停掉除了pg之外的其他容器
pg_dump -h 10.1.1.1 -p 15432 -U postgres -d postgres -T nodestore_node -F c -f /root/backup_mydb_other.dump

# 导出 nodestore_node 的数据(分段)
pg_dump -h 10.1.1.1 -p 15432 -U postgres -d postgres -t nodestore_node --schema-only -f /root/nodestore_node_schema.sql

psql -h 10.1.1.1 -p 15432 -U postgres -d postgres -c \
"COPY (SELECT id, data, timestamp FROM public.nodestore_node WHERE timestamp >= '2025-07-08 00:00:00+08' AND timestamp < '2025-07-10 00:00:00+08') TO STDOUT" > /root/nodestore_node_part1.csv

psql -h 10.1.1.1 -p 15432 -U postgres -d postgres -c \
"COPY (SELECT id, data, timestamp FROM public.nodestore_node WHERE timestamp >= '2025-07-06 00:00:00+08' AND timestamp < '2025-07-08 00:00:00+08') TO STDOUT" > /root/nodestore_node_part2.csv

psql -h 10.1.1.1 -p 15432 -U postgres -d postgres -c \
"COPY (SELECT id, data, timestamp FROM public.nodestore_node WHERE timestamp >= '2025-07-04 00:00:00+08' AND timestamp < '2025-07-06 00:00:00+08') TO STDOUT" > /root/nodestore_node_part3.csv

第二步:本地恢复(清除 + 还原)

# 清空 public schema(避免冲突)
PGPASSWORD=... psql -U postgres  -c "DROP SCHEMA public CASCADE;"
PGPASSWORD=... psql -U postgres  -c "CREATE SCHEMA public;"
PGPASSWORD=... psql -U postgres  -c "GRANT ALL ON SCHEMA public TO postgres;"
PGPASSWORD=... psql -U postgres  -c "GRANT ALL ON SCHEMA public TO sentry;"

第三步:恢复数据库内容

# 1. 恢复全局对象(角色、权限等)
PGPASSWORD=... psql -U postgres -f /root/backup_mydb_global.sql

# 2. 恢复 main schema 数据(不含 nodestore_node)
PGPASSWORD=... pg_restore -U postgres -d postgres /root/backup_mydb_other.dump

# 3. 创建 nodestore_node 表结构
PGPASSWORD=... psql -U postgres -d postgres -f /root/nodestore_node_schema.sql

# 4. 分批导入 nodestore_node 数据
PGPASSWORD=... psql -U postgres -d postgres -c "COPY public.nodestore_node (id, data, timestamp) FROM STDIN" < /root/nodestore_node_part1.csv
PGPASSWORD=... psql -U postgres -d postgres -c "COPY public.nodestore_node (id, data, timestamp) FROM STDIN" < /root/nodestore_node_part2.csv
PGPASSWORD=... psql -U postgres -d postgres -c "COPY public.nodestore_node (id, data, timestamp) FROM STDIN" < /root/nodestore_node_part3.csv

总结

  1. 备份时注意 -T 排除 nodestore_node,由于单表空间过于大,导致失败;
    恢复前用 DROP SCHEMA;
  2. 只恢复一次 global.sql;
  3. 创建 nodestore_node 表结构后再导入 CSV 数据;
  4. 保证顺序是:schema → dump → 手动 COPY 数据。

结果(Result)

Self-Hosted Sentry 的pg迁移后,验证一切功能正常,历史数据完好。