柜员给客户存错了钱、清算参数配错算错了费、程序 bug 多扣了一笔——账务出错是天天发生的事。处理方式是券商系统和互联网系统分道扬镳的地方。互联网的直觉是"把错的数改对":UPDATE balance SET ...。券商账务系统里这是禁令:流水和凭证一旦入账永不可改,纠错只能靠两笔新的账——一笔红字把错的冲掉,一笔蓝字把对的补上。这篇讲这套纪律的原因和实现。
为什么不能 UPDATE
三条理由,层层递进。
审计要求不可抵赖。 账本的存在意义是"事后能还原发生了什么"。UPDATE 流水等于销毁现场:改完之后,没有人知道原来的数是多少、谁改的、为什么改。监管现场检查调取历史流水时,账上每一笔都要能对应当初的原始凭证;出现"余额和流水对不上但说不清原因"的账户,性质等同做假账。append-only 的账本让"还原任意时点状态"成为可能:把流水从期初重放到该时点,状态必然重现——UPDATE 破坏的就是这个可重放性。
余额连续性会被打断。 流水上的"变动后余额"构成一条链:上一笔的"变后"必须等于下一笔的"变前"。UPDATE 改掉中间一笔的金额,整条链从修改点往后全部断裂,账户上所有后续流水的"变后余额"都成了错的。要修复只能级联重算该账户修改点之后的全部流水——生产系统里没有任何安全的方式做这件事。
并发下 UPDATE 不可控。 账务热点账户每秒有几十笔变动在发生,UPDATE 一笔历史流水时,新流水还在基于"错误的旧余额"继续往下写。改完的瞬间,刚写入的新流水又失效了。append-only 没有这个问题:新记录永远在链尾追加,纠错记录和普通业务记录地位平等。
红冲蓝补的操作语义
红字冲销(红冲):做一笔和原错误分录借贷方向相同、金额为负(会计实务中用红字表示,系统里就是负数或"红字"标志位)的分录,把原分录的效果完全抵消:
原错误凭证:借 客户资金-张三 1000 贷 清算备付金 1000
红字冲销: 借 客户资金-张三 -1000 贷 清算备付金 -1000
两笔相加,两个科目的净效果归零——但账上留下了两条记录,现场完整保留:发生过一笔错账,然后被冲掉了。
蓝字补记(蓝补):再做一笔正确的分录,把本来该记的账补上:
蓝字补记: 借 客户资金-李四 1000 贷 清算备付金 1000
这套语义的关键性质:纠错的效果发生在当前,而不是过去。张三的账上不是"历史被改了",而是"历史上有一笔错入,今天有一笔冲出",两个时点各自的余额链都是连续的。这正是可重放性保全下来的原因。
联机冲正:红冲的实时版本
红冲蓝补有一个联机世界的近亲:冲正(reversal)。柜员 10:00 给客户存错了一笔,10:05 发现,客户当天还有别的交易——这时候不能等到日终走调账流程,要立刻冲正:发一笔冲正交易,引用原流水号,全额反向,原流水打"已冲正"标志,冲正流水打"冲正"标志,两笔配对。资金系统的冲正约束比日终调账更严:
- 必须全额,不允许部分冲正(部分纠错拆成"全额冲正 + 重新做一笔正确金额的");
- 原流水状态校验:已被冲正的流水不能再冲,已终结的委托(已成交)不在柜员冲正权限内——成交的纠正是交易所层面的事,券商冲正权限只覆盖柜面类业务(存取款、费用收取);
- 幂等:同一个冲正请求重复提交(柜员双击、网络重试)只能生效一次,靠原流水的"已冲正"标志 + 冲正表的唯一约束双重防重。
隔日差错:为什么不能冲"昨天的账"
当日差错可以当日冲正,因为账还"活着":当日批量没跑、试算平衡还没校验、报表还没出。隔日发现的差错绝对不允许回去冲昨天的账——昨天的账已经日切封存:凭证号序列已闭合、科目余额已滚动、对账已完成、监管日报已报送。回到昨天插入一笔,等于让已报送的数据和库里的数据不一致。
隔日差错的处理是在发现日做调整分录:红冲和蓝补都记在今天,分录上注明调整的是哪一天的哪笔业务。这样昨天的账保持封存原样,今天的账里多了一笔"更正昨日差错"的记录,报表口径上体现为"本期调整"。这正是红冲蓝补相对于 UPDATE 的另一个优势:调整的影响落在哪个会计期间,是会计上有明确答案的问题,append-only 让期间边界不可穿越,UPDATE 则直接把期间边界抹掉了。
跨月的差错还涉及已出报表的更正声明,跨年的涉及审计调整——层级越深流程越重。这就是为什么对账体系追求"当日发现":当日差错是一笔冲正的事,隔日是一笔调整分录的事,隔月是一场审计沟通的事。
工程实现清单
- 流水表/凭证表在数据库层面禁 UPDATE/DELETE(去掉应用账号的相应权限,只留 INSERT/SELECT);
- 红冲记录必须存原凭证号/原流水号的外键引用,金额全额对冲由约束或生成器保证;
- 冲正/调账是独立的业务类型,走审批流(金额分级:小额主管批,大额双人复核 + 合规),全程留痕;
- 红冲蓝补生成的分录参与当天试算平衡——它们本身就是正常记账,不改变日终校验的形状;
- 给运营一张"差错台账"视图:原凭证、红冲、蓝补、审批人、原因分类,监管检查要的第一份材料就是它。
append-only + 红冲蓝补本质上是用存储和操作的冗余换历史的不可篡改性。多写一笔账、多走一道审批,成本很低;换来的是任意时点可重放、审计可穿透、差错可追溯。账务系统里所有关于"能不能直接改"的讨论,答案在几百年前就定了:不能,冲掉重来。