【踩坑实录】Supernote 私有云灾难恢复实录:从数据全毁到完美重建的 48 小时
Supernote 私有云灾难恢复实录
Supernote 私有云灾难恢复实录:从数据全毁到完美重建的 48 小时
一、事故回顾:一次断电引发的连锁反应
事情要从一次意外的断电说起。
我的 Synology DS923+ NAS 经历了几次突然断电,最初只是觉得运气不好,重启后一切似乎正常。然而几天后,4 号硬盘(8T)突然报状态为 Critical,整个 SHR 存储池被降级。更换新硬盘后,噩梦才真正开始——系统文件已经损坏到无法通过常规手段修复的程度。
按照官方技术支持的建议,我不得不走上一条“备份全部数据 → 删除 Volume → 重新创建 Volume → 恢复所有数据”的道路。
当时我的系统配置是:
- 群晖 DS923+
- 4 块硬盘:4T + 4T + 8T + 8T,组成 SHR RAID
- 2TB SSD 缓存 + 16GB 内存
- 部署了多个服务,除了mysql、share drive以外,还包括 Supernote 私有云,详细部署过程参见这篇文章
重建存储池和恢复基础数据的过程虽然繁琐但有章可循,真正的挑战来自 Supernote 私有云。这个自建服务在数据恢复后反复报错,登录始终失败,在通过网页登录私有云时提示“Account or Password Error”,创建新用户、重置密码均无法解决问题,耗费了整整两天时间才彻底解决。
我把整个过程记录下来,希望能帮到遇到类似问题的朋友。
二、私有云故障的核心症状
数据恢复后,Supernote 私有云出现以下现象:
- 登录始终报错“Account or password error”,即使通过官方渠道重置密码也无法解决
- 容器日志反复出现
TooManyResultsException: Expected one result... but found: 2 u_user表中明明只有一个用户,但错误依然存在- 即使清空所有表数据、重建容器,错误依然顽固
这个错误信息成了整个排查过程中的“噩梦模式”——它像幽灵一样挥之不去,让我一度怀疑自己是不是碰到了无法解决的 Bug。
三、踩坑与排错:一个曲折的定位过程
第 1 坑:以为只是重复用户的问题
最初看到 TooManyResultsException,第一反应是数据库里存在重复的用户记录。检查 u_user 表后,确实发现两个用户(一个是我原来的账号,一个是后来为了测试创建的新账号)。删除新用户后,问题依旧。
经验教训:不要只盯着 u_user 表。Supernote 的登录验证会关联查询多个表。
第 2 坑:逐一排查 26 张表
通过查询所有包含 user_id 字段的表,发现以下表都有数据:
e_temp/e_temp_nowe_user_equipment/e_user_equipment_recordf_capacity/f_file_action/f_file_convertf_file_his_sync/f_file_server_changef_recycle_file/f_share_record/f_user_filet_schedule_*系列(多张定时任务表)t_summary/t_summary_tagu_commonly_area/u_commonly_equipmentu_data_migration_record/u_sensitive_recordu_user_history/u_user_sold_out/u_login_record
逐一删除另一个用户的残留数据后,重启容器——问题依然存在!
第 3 坑:清空所有表数据仍然无效
此时我已经开始怀疑人生。为了彻底排除数据问题,执行了清空所有 26 张表的操作,重新注册账号。结果——依然是 TooManyResultsException。
这说明问题根本不在数据层面。
第 4 坑:发现真正的根源
重新检查 docker-compose.yml,发现一个致命问题:所有服务没有配置自定义网络。
Supernote 私有云需要以下四个服务协同工作:
mariadb:数据库redis:缓存notelib:笔记库服务supernote-service:主服务
如果没有将它们放在同一个自定义网络(supernote-net)中,supernote-service 就无法通过主机名 mariadb 连接到数据库,导致启动失败。
正确的网络配置:
services:
mariadb:
networks:
- supernote-net
redis:
networks:
- supernote-net
notelib:
networks:
- supernote-net
supernote-service:
networks:
- supernote-net
networks:
supernote-net:
name: supernote-net
driver: bridge
第 5 坑:设备绑定标识无法清除
即使私有云服务恢复正常,设备端仍然提示“必须登录原来绑定的私有云账号”。这是因为 Supernote 设备在首次绑定私有云时,会在本地存储一个与该私有云实例绑定的唯一标识。
清空数据库、重建容器都无法解决这个问题。最终只能通过以下流程解决:
- 通过 USB 将设备上的所有文件(
Note、Document、Export等文件夹)完整备份到电脑 - 登录官方 Supernote 云,将笔记同步到官方服务器(作为中转)
- 恢复出厂设置
- 从电脑备份恢复所有文件
- 重新连接私有云
四、正确的完整重建流程
以下是经过验证的、能够彻底解决私有云登录问题的完整流程:

第一步:备份设备数据(最重要)
# 通过 USB 连接 Supernote 到电脑
# 将整个设备的所有文件夹复制到本地:
# - Note/ (笔记文件)
# - Document/ (文档)
# - Export/ (导出文件)
# - MyStyles/ (样式)
# - ScreenShot/(截图)
# - MyScripts/ (脚本)
千万不要只依赖系统内置的“备份摘录”功能,那个只有 15MB,而你的真实数据可能是 14GB!
第二步:通过官方云中转数据
在设备上登录官方 Supernote 账号
将所有笔记同步到官方云
访问 https://cloud.supernote.com 确认数据完整
第三步:恢复出厂设置
设备设置 → 系统 → 恢复出厂设置
第四步:从电脑恢复数据
USB 连接电脑,将备份的所有文件夹复制回设备
登录官方云,同步确认数据完整
第五步:正确的私有云部署
# docker-compose.yml 核心配置(完整版)
version: '3.8'
services:
mariadb:
image: mariadb:10.6.24
container_name: supernote-mariadb
networks:
- supernote-net
environment:
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: supernotedb
MYSQL_USER: supernote_user
MYSQL_PASSWORD: your_user_password
volumes:
- /path/to/mariadb_data:/var/lib/mysql
restart: unless-stopped
redis:
image: redis:7.4.7
container_name: supernote-redis
networks:
- supernote-net
command: redis-server --requirepass your_redis_password
volumes:
- /path/to/redis_data:/data
restart: unless-stopped
notelib:
image: docker.io/supernote/notelib:6.9.3
container_name: supernote-notelib
networks:
- supernote-net
restart: unless-stopped
supernote-service:
image: docker.io/supernote/supernote-service:26.02.23
container_name: supernote-service
networks:
- supernote-net
ports:
- "18072:18072" # 设备同步端口
- "19072:8080" # Web 界面端口
volumes:
- /path/to/sndata/recycle:/home/supernote/recycle
- /path/to/supernote_data:/home/supernote/data
- /path/to/sndata/logs/cloud:/home/supernote/cloud/logs
- /path/to/sndata/logs/app:/home/supernote/logs
- /path/to/sndata/logs/web:/var/log/nginx
- /path/to/sndata/convert:/home/supernote/convert
- /etc/localtime:/etc/localtime:ro
environment:
MYSQL_DATABASE: supernotedb
MYSQL_USER: supernote_user
MYSQL_PASSWORD: your_user_password
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: your_redis_password
depends_on:
- mariadb
- redis
- notelib
restart: unless-stopped
networks:
supernote-net:
name: supernote-net
driver: bridge
第六步:启动服务
cd /path/to/supernote/
sudo docker-compose down -v # 彻底清理
sudo docker-compose up -d # 全新启动
五、避坑指南:经验总结
🔴 致命错误(会导致服务完全不可用)
| 错误 | 后果 | 正确做法 |
|---|---|---|
| 未配置自定义网络 | 服务无法连接数据库,启动失败或 502 错误 | 所有服务必须在同一个 networks 下 |
忘记配置 depends_on |
主服务在数据库就绪前启动,连接失败 | 明确声明服务依赖关系 |
直接删除 u_user 表数据 |
残留数据导致登录验证失败 | 通过官方渠道删除用户,或清空所有关联表 |
🟡 常见陷阱(会导致登录失败)
| 陷阱 | 现象 | 解决方法 |
|---|---|---|
| 数据库存在重复的 email | TooManyResultsException |
确保 u_user.email 唯一 |
| 残留的设备绑定记录 | 新账号无法登录 | 清空 e_user_equipment、e_equipment_authorize 表 |
| 容器启动顺序问题 | 数据库连接超时 | 使用 depends_on 确保顺序 |
🟢 最佳实践
- 使用自定义网络:所有服务都需要显式声明加入同一个网络,这是最常见的问题根源
- 数据持久化:使用
volumes映射数据目录,避免容器删除导致数据丢失 - 设备绑定与恢复:
- 备份:USB 完整复制 + 官方云同步(双重保险)
- 恢复出厂设置前:务必备份所有文件
- 恢复后:设备会作为新设备绑定,数据从设备同步到私有云
- 端口说明:
19072:Web 管理界面(映射容器 8080)18072:设备同步服务
六、结语
回顾这次 48 小时的折腾,最初的几小时都在错误的方向上浪费时间——以为删掉重复用户就能解决,结果发现还有 26 张表需要清理;以为清空所有表就能重新开始,结果发现网络配置才是根本问题。
最深刻的教训是:当一个问题持续无解时,要敢于怀疑最初的假设。TooManyResultsException 并不一定意味着数据库真的有多条记录,也可能是服务根本没有正确连接到数据库。
另外,Supernote 设备端的备份机制有很强的误导性。那个 15MB 的“备份”只包含摘录,不包含你的千辛万苦写下的笔记。完整备份必须通过 USB 连接电脑,直接复制所有文件夹。
希望这篇文章能帮助你避开我踩过的坑。如果你也在自建 Supernote 私有云,建议先在测试环境验证网络配置的正确性,再投入正式使用。
最后更新:2026年5月
更多推荐
所有评论(0)