最近,在将 Authentik 从版本 2024.6.3
升级到 2024.12.0
的过程中, Authentik 新版本需要升级 PostgreSQL 数据库版本,从 12
升级到了 16
。整个升级过程总体较为顺利,但在尝试通过 pg_restore
恢复数据时,却意外遇到了 (segmentation fault) 。
问题背景 {#问题背景}
升级步骤大致如下:
-
✅ 使用 Docker 容器管理 PostgreSQL 和 Authentik。
-
📦 在升级前,通过以下命令将 PostgreSQL 数据库的内容备份到宿主机:
|-----------|-------------------------------------------------------------------------| |
1
|docker exec -ti <容器id> pg_dump -Fc -U <数据库用户名> <数据库名> > db.dump
| -
🛠️ 安装新的 Authentik 和 PostgreSQL 容器。
-
🔄 尝试使用以下命令恢复数据:
|-------------|---------------------------------------------------------------------------------------------------------------| |
1 2
|docker cp db.dump <容器id>:/db.dump docker exec -ti <容器id> pg_restore -U <数据库用户名> -c -d <数据库名> /db.dump
|
然而,在执行恢复时,窗口没有报错,也没有任何恢复效果。随后,我进入容器,手动执行 pg_restore
:
|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3
| docker exec -it <容器id> bash <容器id>:/# pg_restore -Fc -h localhost -U <数据库用户名> -d <数据库名> /tmp/db.dump Segmentation fault (core dumped)
|
这时,命令直接报错:**Segmentation fault (core dumped)**。
解决方法 {#解决方法}
为了解决这个问题,我在 stackoverflow
中找到了,关键在于避免通过 stdout
传递二进制数据。以下是改进后的备份和恢复步骤。
1. 正确备份方法 {#1-正确备份方法}
📤 直接在容器内部生成备份文件:
|-----------|----------------------------------------------------------------------------------------|
| 1
| docker exec -ti <容器id> bash -c 'pg_dump -Fc <数据库名> -U <数据库用户名> > /tmp/db.dump'
|
📥 然后将备份文件从容器复制到宿主机:
|-----------|-------------------------------------------------|
| 1
| docker cp <容器id>:/tmp/db.dump ./db.dump
|
2. 正确恢复方法 {#2-正确恢复方法}
📤 将备份文件复制回容器:
|-----------|-----------------------------------------------|
| 1
| docker cp db.dump <容器id>:/tmp/db.dump
|
🔄 在容器内恢复数据:
|-----------|---------------------------------------------------------------------------------|
| 1
| docker exec -ti <容器id> pg_restore -U <数据库用户名> -c -d <数据库名> /tmp/db.dump
|
总结和建议 {#总结和建议}
在升级 Authentik 和 PostgreSQL 的过程中,我因为使用不正确的备份和恢复方式,导致了 pg_restore
报错分段错误。这次经验让我认识到:
- ⚠️ 备份和恢复二进制数据时要小心处理传输环节,尤其是通过管道或
**stdout**
的传输方式 。 - ✅ 更安全的做法是直接在容器内生成和使用备份文件,减少中间数据传输带来的风险。
希望这篇文章能帮助到和我一样在升级 PostgreSQL 和 Authentik 的过程中遇到问题的朋友。如果你也有类似问题或更好的解决方法,欢迎在评论中讨论!
引用 {#引用}
stackoverflow: https://stackoverflow.com/questions/63934856/why-is-pg-restore-segfaulting-in-docker