ClickHouse 先删除数据再插入数据不报错,但是没有插入数据的问题

寻龙剑侠 2025-10-23 15:06:08 127 阅读 Database

对副本表 insert 语句的数据会划分为数据块. 每个数据块会生成 block_id ,存在 zookeeper 相应表目录的 block 子目录下.根据这个 block_id 数据块会去重.当对这份数据进行 aleter delete 操作后.数据成功删除了,但是存在 zookeeper 上的 block_id 没有被一并删除.导致之后对这份数据进行 insert into ,会被表引擎判断为重复数据,而被略过,使数据没有落地到表里面.也就是查不出来这份数据.

场景回顾

我有一张基础表 A 和宽表 B ,宽表B的字段是从A表中抽出来的,在处理数据A、B表更新数据时,出现了B表的数据更新不了的问题。更新逻辑:先将需要更新的数据插入临时表,再以临时表的id作为条件删除A、B表的数据,再将临时表的数据插入A、B表实现数据更新。在处理A表的时候,这个更新逻辑是没有问题的。但是在处理B表的更新时,数据可以删除,但是插入的数据无法查询到,且不报错。导致B表的数据少于预期。

原因

通过在DBever上反复测试,偶尔能插入几条数据,但是删除B表的数据,在插入临时表的数据,这个问题就会出现。 经过查看了多个博文,按照博文的统一说法,clickhouse有一个insert幂等检测机制。会检测数据重复。 A、B表都是副本表引擎,B表删除数据时,删除的数据块产生的block_id,还在zookeeper中,这是有立马插入相同的数据,删除的数据块和插入的数据块生成的block_id是一致的,触发了insert幂等检测机制,这时就会导致insert的数据不会被插入B表中。

为什么A表可以,B表不行能? 实际上临时表的数据相对于A表插入的数据而言,产生的block_id是不一样的(B表的字段仅为A表字段的部分),在A表的其他字段是产生变化了的。 在给B表做删除和插入时,这部分数据在B表中表现为一样的,因此导致了insert幂等检测。

解决方案

按照博文的说法:

  1. 设置 set insert_deduplicate=0 临时关闭去重机制

  2. 找到 zookeeper 下对应的 block_id ,手动删除这个 block_id

按照评论的说法,可能会导致报错或其他问题。需要自己评估

我的解决方案: 不用B表这个宽表了,业务直接使用A表(我的业务场景可以这么干)。

参考博文地址

标签: Apache Nifi

评论

评论先审后显;邮箱仅用于生成头像(MD5),不会公开显示