MariaDB 10.4.18中InnoDB唯一哈希索引致binlog冗余字段的机制问询
问题描述
在MariaDB 10.4.18实例中,一张包含15个字段的InnoDB表对release_seq_no字段创建了唯一哈希索引,但binlog的行数据中额外出现了一个存储大数值的LONGINT字段,导致CDC功能异常。
表结构
CREATE TABLE `xxxx` ( `release_id` int(11) NOT NULL AUTO_INCREMENT, `release_seq_no` varchar(32) DEFAULT NULL, ...... `modify_time` datetime DEFAULT NULL, PRIMARY KEY (`release_id`), UNIQUE KEY `index_release_seq_no` USING HASH (`release_seq_no`)) ENGINE = InnoDB AUTO_INCREMENT = 321206 CHARSET = utf8
binlog内容片段
#Write_rows: table id 58002 flags: STMT_END_F ### INSERT INTO `xxx`.`xxxx` ### SET ### @1=2328410 /* INT meta=0 nullable=0 is_null=0 */ ...... ### @15='2023-10-30 10:01:03' /* DATETIME(0) meta=0 nullable=1 is_null=0 */ ### @16=6755689043813728036 /* LONGINT meta=0 nullable=1 is_null=0 */ # Number of rows: 1
问题原因与解决方案
原因分析
这个额外的LONGINT字段是InnoDB为哈希索引维护的虚拟哈希值存储列。
InnoDB并没有原生纯哈希索引实现,通过USING HASH创建的哈希索引,本质是基于B+树构建的——内部会为哈希索引字段生成对应的哈希值,将这个哈希值作为虚拟列存储在B+树中,以此实现哈希索引的快速查找逻辑。当记录写入binlog时,这个内部维护的虚拟哈希值列会被一同输出,导致binlog中的字段数比表结构定义多1个。
这种行为在MariaDB 10.4版本的InnoDB哈希索引场景下会稳定出现,而CDC工具通常基于表结构定义的字段数和顺序解析binlog,额外字段会打破原有字段映射关系,进而引发CDC功能异常。
解决方案
替换为BTREE唯一索引
InnoDB哈希索引适用场景有限(仅等值查询有优势,不支持范围查询),且本质依赖B+树实现。将哈希索引改为BTREE唯一索引后,不会生成额外的虚拟哈希值列,binlog字段数会与表结构一致,彻底解决CDC异常问题。修改语句如下:ALTER TABLE `xxxx` DROP INDEX `index_release_seq_no`, ADD UNIQUE KEY `index_release_seq_no` USING BTREE (`release_seq_no`);调整CDC解析逻辑
如果业务必须保留哈希索引,需要在CDC工具的解析逻辑中添加过滤规则:识别并忽略这个额外的LONGINT字段,或者重新调整字段映射关系,将原15个字段与binlog中前15个字段对应。
内容的提问来源于stack exchange,提问作者Roc King
相关产品推荐
相关产品推荐

