官方文档: Backup and Restore | TeslaMate
这篇文章把我之前博客里的基础备份恢复方法,以及最近实际在用的 bump 备份方案整合到一起。
如果你只是想快速上手,建议优先看前面的 bump 方案;如果你只是单机手动维护,也可以看后面的基础命令版。
custom format dump,也就是 pg_dump -Fcpg_restoreteslamate 应用容器,数据库容器保持运行public 和 private 两个 schema,避免新版本迁移时出现 private.tokens 冲突docker-compose.yml、.env 一起保存这是我现在更推荐的方案,适合长期运行、批量管理、远程自动备份。
bump 目录里的脚本,本质上做的是下面这些事情:
pg_dump -Fc 生成完整数据库备份相比早期直接导出 .bck 文本 SQL,这种方式有几个优点:
建议做法:停止 teslamate 应用容器,再执行备份。
原因:
推荐状态:
teslamate 容器:停止postgres 容器:保持运行grafana、mosquitto、wemate:可停可不停不过如果你不能接受短暂停机,也可以在线备份。pg_dump 本身支持一致性快照导出,所以不停机备份通常也是可用的,只是从运维稳妥性上略弱一些。
我现在的脚本已经支持这两种模式:
STOP_TESLAMATE_BEFORE_BACKUP=1:先停应用再备份STOP_TESLAMATE_BEFORE_BACKUP=0:不停机直接在线备份如果你只是给自己使用,并且更在意不中断服务,可以直接在线备份。
如果你准备给别人做迁移、恢复,或者希望尽量降低恢复翻车概率,还是建议先停应用再备份。
下面示例假设:
teslamate-database-1teslamate-teslamate-1teslamateteslamate./teslamate.dumpbashdocker stop teslamate-teslamate-1
docker exec teslamate-database-1 pg_dump -U teslamate -d teslamate -Fc -f /teslamate.dump
docker cp teslamate-database-1:/teslamate.dump ./teslamate.dump
docker exec teslamate-database-1 rm -f /teslamate.dump
docker start teslamate-teslamate-1
bashdocker exec teslamate-database-1 pg_dump -U teslamate -d teslamate -Fc -f /teslamate.dump
docker cp teslamate-database-1:/teslamate.dump ./teslamate.dump
docker exec teslamate-database-1 rm -f /teslamate.dump
参数说明:
-U teslamate:数据库用户-d teslamate:数据库名-Fc:使用 PostgreSQL 自定义格式导出-f /teslamate.dump:在数据库容器中生成临时备份文件备份完成后,先看文件是否存在、大小是否正常:
bashls -lh ./teslamate.dump
如果还想进一步验证备份结构,可以查看归档内容:
bashpg_restore -l ./teslamate.dump
如果输出里能看到表、schema、索引等对象,通常说明这个备份文件结构上是有效的。
除了数据库备份文件,建议再额外保存:
docker-compose.yml.env 或相关环境变量文件原因很简单:很多恢复失败,不是备份文件坏了,而是恢复时直接用了不合适的新版本。
查看镜像版本可以用:
bashdocker ps --format 'table {{.Names}}\t{{.Image}}'
docker inspect teslamate-teslamate-1 --format '{{.Config.Image}}'
docker inspect teslamate-database-1 --format '{{.Config.Image}}'
推荐把这些信息和 teslamate.dump 放在同一个备份目录里。
恢复时的核心原则:
很多人恢复失败,根本原因不是“不会导入”,而是把下面三种状态混在了一起:
所以更稳妥的思路是:先恢复干净数据库,再启动 TeslaMate。
特别注意:新版 TeslaMate 会使用 private schema 存放部分敏感表。如果目标数据库之前已经被新版本启动过,或者迁移失败过,里面可能已经有 private.tokens。这时再恢复旧备份,TeslaMate 启动迁移时会尝试把 public.tokens 移到 private.tokens,然后报错:
textERROR 42P07 (duplicate_table) relation "tokens" already exists in schema "private"
解决方法不是改 compose,而是在恢复前明确清空 public 和 private 两个 schema。
假设:
./teslamate.dumpbashdocker stop teslamate-teslamate-1
如果你使用的是 docker compose,也可以这样停:
bashdocker compose stop teslamate grafana docker compose up -d database
pg_dump -Fc 生成的 custom dump 文件开头通常是 PGDMP:
bashhead -c 5 ./teslamate.dump
echo
如果输出是 PGDMP,就用 pg_restore。如果输出是 -- 或者能看到 SQL 文本,那是普通 SQL dump,参考后面的“基础命令版恢复”。
bashdocker exec -i teslamate-database-1 psql -U teslamate -d teslamate <<'SQL'
DROP SCHEMA IF EXISTS public CASCADE;
DROP SCHEMA IF EXISTS private CASCADE;
CREATE SCHEMA public;
CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public;
SQL
如果你使用的是 docker compose 服务名:
bashdocker compose exec -T database psql -U teslamate -d teslamate <<'SQL'
DROP SCHEMA IF EXISTS public CASCADE;
DROP SCHEMA IF EXISTS private CASCADE;
CREATE SCHEMA public;
CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public;
SQL
这一步是为了避免目标库残留新版本创建的 private.tokens,导致恢复后 TeslaMate 迁移失败。
方式 A:先复制到数据库容器内再恢复:
bashdocker cp ./teslamate.dump teslamate-database-1:/teslamate.dump
docker exec teslamate-database-1 pg_restore -U teslamate -d teslamate --clean --if-exists --no-owner --role=teslamate /teslamate.dump
docker exec teslamate-database-1 rm -f /teslamate.dump
方式 B:直接从当前目录管道恢复,适合 docker compose:
bashcat ./teslamate.dump | docker compose exec -T database pg_restore -U teslamate -d teslamate --clean --if-exists --no-owner --role=teslamate
pg_restore:恢复 pg_dump -Fc 生成的备份--clean:恢复前按备份归档里的对象清理旧对象--if-exists:对象不存在时忽略删除报错--no-owner:不强制恢复原数据库对象 owner,跨机器迁移更稳--role=teslamate:用当前环境里的 teslamate 角色创建对象private,是为了处理旧 dump 里没有 private schema、但目标库已经残留 private.tokens 的情况bashdocker start teslamate-teslamate-1
如果使用 docker compose:
bashdocker compose up -d
bashdocker logs -f teslamate-teslamate-1
如果使用 docker compose:
bashdocker compose logs -f teslamate
先检查容器是否正常运行:
bashdocker ps
查看 TeslaMate 最近日志:
bashdocker logs --tail 100 teslamate-teslamate-1
如果要进一步检查 PostgreSQL 里的表和迁移记录:
bashdocker exec -it teslamate-database-1 psql -U teslamate -d teslamate
检查表:
sqlSELECT schemaname, tablename
FROM pg_tables
WHERE schemaname IN ('public', 'private')
ORDER BY schemaname, tablename;
检查迁移记录:
sqlSELECT version FROM schema_migrations ORDER BY version;
以下情况,不建议直接往当前数据库硬导入:
更稳妥的做法是:
如果你只是单机手动操作,也可以继续使用以前这种基础命令方式。
不过要注意,这种 .bck 方式本质是 SQL 文本导出,适合简单场景,不如 pg_dump -Fc 稳妥。
假设你的目录是:
bashcd /home/pi/teslamate
执行备份:
bashdocker compose exec -T database pg_dump -U teslamate teslamate > ./teslamate.bck
如果当前目录生成了 teslamate.bck,说明备份已完成。
先停止 TeslaMate:
bashdocker compose stop teslamate docker compose up -d database
重建 schema 和扩展。这里必须同时清理 public 和 private,否则新版本 TeslaMate 可能会因为 private.tokens 已存在而迁移失败:
bashdocker compose exec -T database psql -U teslamate -d teslamate <<'SQL'
DROP SCHEMA IF EXISTS public CASCADE;
DROP SCHEMA IF EXISTS private CASCADE;
CREATE SCHEMA public;
CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public;
SQL
进入备份目录:
bashcd /home/pi/teslamate
导入备份文件:
bashdocker compose exec -T database psql -U teslamate -d teslamate < teslamate.bck
如果你的文件开头是 PGDMP,说明它不是文本 SQL,而是 pg_dump -Fc 生成的 custom dump。不要用上面的 psql < teslamate.bck,改用:
bashcat teslamate.bck | docker compose exec -T database pg_restore -U teslamate -d teslamate --clean --if-exists --no-owner --role=teslamate
最后启动 TeslaMate:
bashdocker compose start teslamate
pg_dump -Fc 和 pg_restorelatest 标签使用 pg_dump -Fc 备份完整 PostgreSQL 数据库,恢复到干净的数据库环境中,并优先使用与备份来源一致或接近的 TeslaMate 版本启动,整体成功率会高很多。
本文作者:口水
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!