- hass: Scribe 3.8.0 → 4.4.0(HACS jonathan-gtd/scribe,2026-09-13 随 Core 2026.9.1 / HAOS 18.2 升级)。记录 4.0 两个 breaking change 在本机均无需动作 (3.x 结构 DB + PK 在、TimescaleDB 2.29.2 已装)、配置优先级 YAML > options > entry data > 默认值、以及「YAML 改动必须重启 Core」。 - hass: 新增 stats_io_interval: 300(备份 scribe.yaml.bak-20260913-191558)。 变更前 24h scribe 自写 11 019/87 461 行(12.6%);实测发布间隔 300s。 retention_states/retention_events 可用但刻意不设;flush_interval 仍被 entry data 钉在 5s(采用新默认 30s 需显式写 YAML)。 - pgdb: sensor_minute 2.26 GB 是压缩窗口内的正常暂存(compress_after 按 chunk 结束时间判断,09-17 才合格),稳态 4–5 GB 平台期,暂不处理;复查点 09-17 之后。顺带修正 hass/scribe 库体积事实。 校验:scripts/validate-repo.sh PASS (0 warnings)。
13 KiB
13 KiB
pgdb — TimescaleDB (PG18, Docker)
Role and access
| Item | Value |
|---|---|
| Role | TimescaleDB PostgreSQL 18 (Docker) — Home Assistant recorder 后端(hass/scribe 库) |
| IPv4 | 192.168.55.15 (LAN55) |
| DNS | (none) |
| SSH | ssh -4 windy@192.168.55.15(key auth 已验证可用 2026-08-29;agent 沙箱用 ssh -F /dev/null -o BatchMode=yes;password auth 亦可) |
| Host | PVE 管理的 QEMU VM(i440FX,VMID 100),Debian 13 (trixie),内核 6.12.105;宿主机 pve2 192.168.55.25(Proxmox 9.2.2,SSH root@192.168.55.25,onboot: 1,QEMU guest agent 已装;2026-08-31 补记) |
| Resources | 3 GB RAM(08-30 13:58 由 2G 上调、删除 balloon/ksm/shares 后重启生效)/ 30 GB disk(26 G 空闲) |
| Docker | 29.7.2;容器 timescaledb = timescale/timescaledb:latest-pg18(PG 18.6 + TimescaleDB 2.29.2,Apache-2.0 版) |
| Ports | 192.168.55.15:5432(PG,IPv4 only);192.168.55.15:8081(pgweb GUI,basic auth) |
Databases
| DB | Owner | Size | 用途 |
|---|---|---|---|
hass |
hass | ~406 MB(2026-09-13) | HA recorder(states/events/statistics),客户端 HAOS 192.168.55.11 |
scribe |
postgres | ~2.6 GB(2026-09-13) | HA scribe 集成(entities/areas/devices 注册表同步 + states_raw/events hypertable + csg_history 长期归档表);体积由 sensor_minute 图表管道主导(2.26 GB),见 Known issues |
postgres |
postgres | ~9 MB | 默认库 |
Ops notes
- Docker compose 管理(2026-08-29 改造):
/opt/database/docker-compose.yml(源码在仓库compose/pgdb/)+/opt/database/.env(0600,密钥)+/opt/database/pgweb-bookmarks/(0600,bookmark 含 DB 密码)。三个服务:服务 镜像 端口 说明 timescaledbtimescale/timescaledb:latest-pg18192.168.55.15:5432(IPv4 only)PG 18.6 + TS 2.29.2;healthcheck pg_isready; restart: unless-stoppedpgwebsosedoff/pgweb:latest(v0.17.0)192.168.55.15:8081Web GUI:http://192.168.55.15:8081;basic auth(用户名/密码见 .env PGWEB_AUTH_USER/PASS);--readonly --sessions --bookmarks-only --bookmarks-dir /bookmarks(v0.17.0 不读 PGWEB_BOOKMARKS_DIR env,必须用 flag);bookmarks = hass/scribepg-backupprodrigestivill/postgres-backup-local:latest(=PG18 客户端)— 每日 02:00( TZ=Asia/Shanghai,本地时区)pg_dump -Fc三库 →/opt/database/backups/{daily,weekly,monthly};保留 7 天/4 周/6 月;BACKUP_ON_START - 数据盘:
/dev/sdb1(32G ext4,labelpgdata)挂载/srv/pgdata,fstab 按UUID=c9e12e79-1f66-404c-ab7f-b8809be81d86(defaults,noatime)持久化(2026-08-29 迁移)。容器 bind mount/srv/pgdata:/var/lib/postgresql。 - 容器内 postgres 用户 uid/gid = 70(Debian 系,非 999);迁移数据后需
chown -R 70:70。 - 密码:postgres 超级用户已换强密码(hex,存
/opt/database/.env0600,2026-08-29)。HA 用hass角色不受影响。 - 备份:由
pg-backup容器接管(2026-08-29),宿主机 cron 与/opt/database/pg-backup.sh已退役。恢复用pg_restore(custom format)——2026-08-29 已实测还原 hass 库 dump(states 10014 行)成功。 - 认证:外部连接 scram-sha-256(密码必填,改密码有效);容器内 loopback 为 trust(官方镜像默认)。
- 回滚:旧启动命令保留在
/opt/database/run(容器无状态,数据在 /srv/pgdata);旧匿名卷9375195843b950f4e04c34872409ca095e1136520dd019a8e86e2794be06c236(根盘 ~82M)保留作兜底,确认稳定后可docker volume rm。 - 开机自愈(2026-08-30):新增 systemd oneshot
pgdb-compose.service(enabled,源码在仓库compose/pgdb/pgdb-compose.service):After=network-online.target docker.service,开机后幂等执行docker compose up -d,重试直到192.168.55.15:5432监听,重试耗尽--force-recreate兜底(数据在 bind mount,无损)。原因:2026-08-30 开机竞态——docker 恢复容器时 VM IP 尚未可绑(EADDRNOTAVAIL),timescaledb/pgweb 启动失败且 docker 不重试。手动重跑:sudo systemctl restart pgdb-compose.service。 - 本机无防火墙(ufw/nft/iptables 均未装)——待办:如要彻底隔离可加 ufw 白名单 192.168.55.11。
/opt/database/backups/根下残留*-2026-08-29_1359.dump(compose 化之前旧备份机制产物)与backup.log——健康检查只看daily/,残留可清理。- Runbooks:pgdb-health(只读健康检查)、pgdb-restore(pg_restore 还原)、pgdb-update(镜像/compose 升级)。
- CSG 长期归档(2026-08-29, W1N-243):
csg_history表(period date / kind('day'|'month') / usage_kwh / cost / ladder / balance / updated_at,PK(period,kind),GRANT SELECT TO hass)保存南方电网有价值数据:day = 逐日(昨日用电/费用/阶梯/余额,2026-07-01 起),month = 当月累计(用电/费用,2025-01 起)。由 TimescaleDB 每日任务 1008csg_daily_snapshot()(22:30 Asia/Shanghai;TS job 非 pg_cron,本库未装 pg_cron)upsert 维护:取「最新有值行」防瞬态 unknown 竞态;日费用缺原生latest_day_cost时回退 = 昨日用电 × 当前档费率(模板csg_current_ladder_tariff0.639);月费用回退模板csg_this_month_ladder_cost。验证:day 08-28 = 7.66 / 4.89474 / 二档 / 0,month 08 = 302.47 / 180.28。回填来源:集成 attributeshistory_data(59 天)+by_month(19 月)——08-29 前唯一残存历史。回滚:DROP TABLE csg_history+SELECT delete_job(1008)。
Known issues
- 2026-09-13:
sensor_minute体积构成与压缩窗口(只读诊断,暂不处理)。scribe库 2.6 GB =sensor_minute2.26 GB(850 万行 / 16 天,约 56–59 万行/天 = 331 实体 × 1440 分钟 LOCF)+states_raw290 MB +events1.5 MB;hass库另 406 MB。2.26 GB 中 1.50 GB 是 chunk[09-03,09-10]、0.76 GB 是[09-10,09-17],都还没到压缩窗口——TimescaleDB 的compress_after按 chunk 结束时间判断(09-10 结束 + 7 天 = 09-17 才合格),所以「7 天 chunk + 7 天 compress_after」的设计下限就是盘上常驻近 14 天原始数据;已压缩的[08-27,09-03]从 1.04 GB → 1.5 MB(LOCF 重复度极高,~700:1)。任务 1005 健康(30 成功 / 0 失败,最近 09-13 04:18 跑过但无合格 chunk);1002/1003/1006/1007 亦全 Success。稳态估算 ≈ 2 个未压缩 chunk(3–4.5 GB)+ 已压缩归档(约 1.5 MB/周 ≈ 80 MB/年)≈ 4–5 GB 平台期;pgdata 卷 32 G 当前用 3.2 G,可用 27 G,无需处理。复查点 2026-09-17 之后:_hyper_4_6_chunk应转为compressed=true且库体积回落;若仍为 false 才需动手(手动compress_chunk()或调小compress_after)。可选调优:chunk 间隔 7 天 → 1 天 +compress_after→ 2 天,把常驻未压缩量压到 <1 GB(set_chunk_time_interval只对新 chunk 生效,旧 chunk 不重切)。诊断命令:select chunk_name, is_compressed from timescaledb_information.chunks where hypertable_name='sensor_minute';+pg_database_size('scribe')。注意:这是 pgdb 侧对象,HA/scribe 的retention_states管不到它;HA 侧唯一杠杆是少记/少画(等于砍图)。 - 2026-08-29:HA 侧 HACS 集成
custom_components.scribe(YAMLscribe: db_url:,连scribe库)建表被拒(permission denied for schema public,hass 无 CREATE 权限),之后持续报relation "entities" does not exist。已解决:①GRANT CREATE ON SCHEMA public TO hass;(scribe 库)② 重启 HA Core 触发重跑建表。重启后自动创建entities(1591 行)/users/areas/devices/integrations/states_raw表并启用 TimescaleDB 时间序列能力。报错已停止(最后一条 06:06 UTC),states_raw持续写入。2026-08-29 复查:scribe 现有两个 hypertable——states_raw(segmentbymetadata_id、orderbytime)与events(segmentbyevent_type、orderbytime),均 1 维time;压缩已配置(timescaledb_information.compression_settings可见对应行;2.29.x 该视图无compression_enabled列)。 - 2026-08-29:timescale reader 图表对象(配套 hass 的
timescale_database_reader集成 +timescale-plotly-card,上游 SQLremmob/timescale_database_readerSQL/scribe/01+02@bb8776a,以 postgres 执行):sensor_minute_aggregate连续聚合(1 分钟桶,last(state)/last(value),实时聚合开启)+sensor_minute_aggregate_entity视图(joinentities)+sensor_minutehypertable(minute/entity_id/state/value,LOCF 前向填充)。任务:1005sensor_minute压缩(7 天)、1006sensor_minute保留(10 年)、1007every_minute_refresh每分钟增量刷新(含 5 分钟回溯窗口修正)。授权:GRANT SELECT ON sensor_minute_aggregate, sensor_minute_aggregate_entity, sensor_minute, entities TO hass。种子 19529 行(331 实体,自首个数据点起)。刻意跳过了上游脚本对states_raw的 3 个月保留 + 压缩策略语句——与"states_raw永久归档"定位冲突,如需磁盘回收属用户决策(scribe 自己的压缩任务 1000/1001 未动)。 - 2026-08-29:
sensor_minute_refresh本地补丁(类比 tianqi 补丁,重跑上游 02 SQL 后需重打):值 CASE 的ELSE 0→ELSE NULL。原因:scribe 对 unavailable 分钟 value 为 NULL,上游刷新过程兜底写 0;对差分模式的用电图,0→计数器回升会把插座的生命周期累计值(最高 1588 kWh)算进掉线那一小时。同日一次性清理既有脏 0:头部占位行 DELETE 505 行(各实体首次非零分钟之前的 value=0);sensor.%_energy与温湿度实体的 value=0 → NULL(10+16 行,物理上不可能的真 0,图表渲染为断点)。功率实体的中途 0 是真实待机读数,保留。 hass库的 recorder 表仍为普通表(无 hypertable);scribe集成负责时间序列历史(states_raw+eventshypertable)。
Verification history
- 2026-08-31:13:58 重启根因确认,非停电(W1N-263):pve2(
192.168.55.25)任务日志显示 08-30 13:58:00root@pam在 PVE Web UI 修改 VM 100 配置(-delete allow-ksm,balloon,shares -memory 3072),13:58:06 点 Reboot(qmreboot→ 客机 13:58:08 干净 ACPI 关机 → 13:58:13 自动重启)。宿主机全程在线(08-30 09:00 开机至今连续运行 1d12h+),.66.26PVE 及各 VM 均无重启——排除停电。HA recorder 在窗口(13:58:46–47)报 2 次Connection refused,DB 恢复后自动重连,无数据丢失(hass.states/scribe.states_raw13:55–14:02 逐分钟无缺口,recorder 内存队列吸收回写)。13:58:47 三容器已起,13:58:56 自愈单元pgdb-compose.service执行成功——本次自愈按设计工作。同日下午 12:54–12:55 另有一次客机内自重启(无 PVE 任务,工作站 SSH 会话相邻)。08-29 22:19→08-30 09:00 宿主机停机 10h41m 为干净关机(systemd 有序关闭,非停电)。 - 2026-08-30:开机竞态故障 + 修复(W1N-260):09:01 开机后 docker 恢复容器时绑定
192.168.55.15:5432/8081失败(EADDRNOTAVAIL)→ timescaledb/pgweb 停摆至 12:16,pg-backup 开机备份失败(解析不到 timescaledb)→ unhealthy。12:22docker compose up -d --force-recreate修复(三容器回database_default、端口发布、今日备份、pgweb 恢复);用户重启 HA Core 后写入管道恢复。12:43 新增开机自愈 unitpgdb-compose.service(enabled,已实测幂等 reconcile)。pgdb-health 8 项全绿。 - 2026-08-29:首次检查(只读)+ 修复 scribe 权限 + 安装夜间备份。见 Linear vps 项目登记。
- 2026-08-29:compose 改造完成(W1N-227,用户已验收):裸
docker run→/opt/database/docker-compose.yml三服务(timescaledb + pgweb + pg-backup);superuser 换强密码;端口收紧 IPv4;备份容器化(TZ=Asia/Shanghai,cron 02:00 本地);pg_restore还原实测通过;pgweb UI 用户确认可查 hass/scribe 数据。源码在仓库compose/pgdb/。 - 2026-08-29:运维 runbook 落地(W1N-228,已验收):新增
runbooks/pgdb-health.md(只读,8 项诊断全绿)、pgdb-restore.md(流程式,temp-DB 安全还原 + 审批门)、pgdb-update.md(门控命令式,回滚=/opt/database/run + 旧卷);README 索引与 validate-repo.sh 分类同步更新;runbook 命令已对活主机逐条实测(含pg_restore -l校验当日 dump)。同日修正:SSH key auth 可用(facts 原记"密钥未安装"已过时);scribe 新增eventshypertable。 - 2026-08-29:CSG 长期归档 + recorder 365d(W1N-243):建
csg_history表 + attributes 回填(逐日 59 + 逐月 19)+ 每日任务 1008(函数 v2:最新有值行读取、日费用阶梯回退);hasspurge_keep_days30→365(备份configuration.yaml.bak-20260829-purge365)。见 Linear vps W1N-243。