事件日志 产品与架构
别名:
events 表
追加式的事件序列,唯一事实源。`event_id` 用 AUTOINCREMENT 自增主键保证全局单调、跨会话不重复;每行带 `session_id` 外键归属会话。事件日志只 INSERT 绝不 UPDATE——事实只能追加,修正也只能追加新事件。
它是什么
事件日志是追加式的事件序列,唯一事实源。event_id 用 AUTOINCREMENT 自增主键保证全局单调、跨会话不重复;每行带 session_id 外键归属会话(外键保证「事件的会话必须先存在」,孤儿事件根本写不进去)。事件日志只 INSERT 绝不 UPDATE——事实只能追加,修正也只能追加新事件(可以带 supersedes 字段指向前一条)。
为什么 AUTOINCREMENT
SQLite 的 INTEGER PRIMARY KEY 直接复用行号(rowid),自增已保证严格单调;加上 AUTOINCREMENT 还保证即使删过行也不复用编号——事件溯源里编号一旦复用,审计和回放就会错乱。事件日志的全局顺序 = event_id 顺序,这是回放(session-replay)和断线重续(第 16 章)的地基。
纪律与坑
- 只 INSERT 绝不 UPDATE:一旦「改一条事件」成了习惯,审计与回放的可靠性就崩了——你无法确定重放出的历史是不是被篡改过的;
- 投影与事件必须同一事务:先写事件、再单独写投影,进程在两步之间崩溃,投影缺行,读路径与回放结果不一致(第 10 章的
appendEvent用BEGIN...COMMIT包住两件事); - 不要用快照思维写事件表:
events是账本,只进不出;「已读」这类可变状态属于投影或单独的元数据表。